我正在使用DP来解决问题但是没有DP的解决方案,即只是回溯就会给出正确的输出,而只有DP的相同代码会产生错误的输出。无法找出原因。
以下是代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long int lli;
#define oo 1000000007;
lli dp[12][1005];
int a[10][1005];
int n;
lli calc(int alt,int i){
if(dp[alt][i] != -1) {
return dp[alt][i];
}
if(i==n && alt==0) {
return 0;
}
if(alt>9 || alt<0 || i==n) {
return oo;
}
return dp[alt][i] = min(
min(
lli(30) - a[alt][i] + calc(alt ,i+1),
lli(20) - a[alt][i] + calc(alt-1,i+1)
),
lli(60) - a[alt][i] + calc(alt+1,i+1)
);
}
int main(){
int t;
string bl;
scanf("%d",&t);
while(t--){
getline(cin,bl);
memset(dp,-1,sizeof dp);
scanf("%d",&n);
n = n/100;
for(int i=9; i>=0; i--) {
for(int j=0; j<n; j++) {
scanf("%d",&a[i][j]);
}
}
lli ans = calc(0,0);
printf("%lld\n",ans);
if(t!=0) printf("\n");
}
}
输入
1
400
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 9 9 1
1 -9 -9 1
正确的输出是120。
答案 0 :(得分:1)
if(dp[alt][i] != -1) {
return dp[alt][i];
}
lli(20) - a[alt][i] + calc(alt-1,i+1)
你只是(不)幸运,程序没有直接崩溃你!
对于alt == -1
,您只读取递归上的一些随机垃圾。您正在从dp
数组外部读取随机值。
像这样切换它们,它应该工作(或者至少有定义的行为):
if(i==n && alt==0) {
return 0;
}
if(alt>9 || alt<0 || i==n) {
return oo;
}
if(dp[alt][i] != -1) {
return dp[alt][i];
}
无论哪种方式,你的方法根本行不通。您首先遍历深度(找到任何路径!),但遍历顺序必须首先宽泛才能找到最短路径。
这意味着你不能像这样使用递归,但必须在内部循环alt
,在外循环中迭代i
。然后,您可以一步一步填写您的路径字段。
这样的朴素动态编程不是此任务的最佳解决方案。您最好将其视为有向加权图,并应用标准Dijkstra。使用您的方法,您将计算(不需要)所有可能的路线。