问题在于计算所有可能的最终位置以及每个位置存在多少组合。
给定起始位置x=0
,轨道长度m
和跳跃列表。返回区间[-m / 2,+ m / 2]上每个位置的可能结束数。跳跃必须按照给定的顺序进行,但可以采取消极或积极的方式进行。
例如:
L = 40
jumps = 10, 10
解决方案:
-20 : 1 (-10, -10)
0 : 2 (-10,+10 & +10,-10)
20 : 1 (+10,+10)
(所需的输出只是“position:#combinations”对)
我用简单的递归做了,结果还可以。 但是在大量数据中,执行时间只有几分钟或几小时。 我知道通过动态编程,我可以在几秒钟内找到解决方案,但我不知道在这种情况下如何应用动态。
我的实际递归功能是:
void escriuPosibilitats(queue<int> q, map<int,int> &res, int posicio, int m) {
int salt = q.front();
q.pop();
if(esSaltValid(m,posicio,-salt)) {
int novaPosicio = posicio - salt;
if(q.empty()) {
res[novaPosicio]++;
} else {
escriuPosibilitats(q,res,novaPosicio,m);
}
}
if(esSaltValid(m,posicio,salt)) {
int novaPosicio = posicio + salt;
if(q.empty()) {
res[novaPosicio]++;
} else {
escriuPosibilitats(q,res,novaPosicio,m);
}
}
}
q
是剩余跳跃的队列。res
是个别解决方案。posicio
是实际位置。m
是曲目的长度。esSaltValid
是一个检查跳转在轨道长度范围内是否有效的函数。答案 0 :(得分:1)
您可以使用以下想法。设dp [x] [i]是直到跳跃i到达位置x的方式的数量。然后每个x的答案是dp [x] [N],其中N是跳跃的数量。更重要的是,您可以意识到这个dp仅依赖于前一行,然后您可以简单地使用dp [x]并将下一行保存在某个辅助数组中,然后在每次迭代中替换它。代码将是这样的:
const int MOD = (int)(1e8+7);
const int L = 100;
int N = 36;
int dx[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
int dp[L+1];
int next[L+1];
int main() {
int shift = L/2; // to handle negative indexes
dp[shift] = 1; // the initial position has one way to arrive, since you start there
for (int i = 0; i < N; ++i) { // for each jump size
for (int x = -L/2; x <= L/2; ++x) { // for each possible position
if (-L/2 <= x + dx[i] && x + dx[i] <= L/2) // positive jump
next[x + shift] = (next[x + shift] + dp[x + dx[i] + shift]) % MOD;
if (-L/2 <= x - dx[i] && x - dx[i] <= L/2) // negative jump
next[x + shift] = (next[x + shift] + dp[x - dx[i] + shift]) % MOD;
}
for (int x = -L/2; x <= L/2; ++x) { // update current dp to next and clear next
dp[x+shift] = next[x+shift];
next[x+shift] = 0;
}
}
for (int x = -L/2; x <= L/2; ++x) // print the result
if (dp[x+shift] != 0) {
cout << x << ": " << dp[x+shift] << '\n';
}
}
当然,如果L太大而无法处理,您可以压缩状态空间并将结果保存在地图中,而不是数组中。该方法的复杂性为O(L * N)。希望它有所帮助。
编辑:只计算模数为1e8 + 7的所有内容,就是这样。