题意:有多个城市编号为1到 n分别有不同的评分,现在知道了某些城市之间的直航,找一条从起点出发回到起点、沿途经过的城市总评分最大的路径。要求只能从编号低的 到编号高的,所以起点编号为1和n+1
分析:dp[i]表示从1到i的最优解,dp[i]=max(dp[j]+intr[i]),其中 1<= j< i (这个条件可以保证只从编号低的走到编号高的)
这题一开始思路就是对的,不过不停WA,一路排查了各种bug,其中最重要的两个:1.long long 2.多组case 和 n+1 造成intr[]数组越界!以后一定要注意这种情况,数组清空;另外这个递归打印的方法要记住
代码:
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #define INF 1000000007 using namespace std; int t,n,m,index,ok; long long mx; //bug1.0 int rut[200][200],intr[2000]; struct node{ long long x; int pre; int ok; }dp[2000]; void DP() { mx=0; for(int i=1;i<=n;i++) dp[i].x=0,dp[i].pre=i,dp[i].ok=0; dp[n+1].x=0,dp[n+1].pre=1,dp[n+1].ok=0; dp[1].ok=1; //ok用来保证合法路径必须是从1开始的 for(int i=2;i<=n;i++) if(rut[1][i]) dp[i].pre=1,dp[i].ok=1; for(int i=2;i<=n+1;i++){ for(int j=1;j<i;j++){ if(rut[j][i]&&dp[j].ok){ if(dp[i].x<dp[j].x+intr[i]){ dp[i].x=dp[j].x+intr[i]; dp[i].pre=j; dp[i].ok=1; } } } } ok=dp[n+1].ok; if(ok){ mx=dp[n+1].x; index=dp[n+1].pre; //index保存最优解的最后一个城市 } else index=1; return; } void prin(int index) //递归打印路径 { int i=index; if(i!=1){ prin(dp[i].pre); cout<<"->"<<i; } else cout<<"1"; return; } int main() { cin>>t; for(int p=1;p<=t;p++){ memset(rut,0,sizeof(rut)); memset(dp,0,sizeof(dp)); memset(intr,0,sizeof(intr));//最后攻陷的一个bug!顽固bug,很隐蔽,以后多注意 cin>>n; for(int i=1;i<=n;i++) cin>>intr[i]; cin>>m; int a,b; while(m--){ cin>>a>>b; rut[a][b]=1; } cout<<"CASE "<<p<<"#"<<endl; DP(); cout<<"points : "<<mx<<endl; cout<<"circuit : "; prin(index); cout<<"->1"<<endl; if(p!=t)cout<<endl; } }
HDU 1224 Free DIY Tour--DP--(bug集锦)
原文地址:http://blog.csdn.net/ac_0_summer/article/details/46502581