【动态规划+Floyd】OpenJudge3368
OpenJudge上刷水都不会了……这题居然写了一个半小时……
【题目大意】
诸葛亮要征服N城市。然而,City-X在击败City-2,City-3……City-x-1后击败。关羽,张飞,赵云,每个人都应该领导一个军队。三个军队从City-0出发,征服所有的城市。求三个军队的行程总长的最小值。
【思路】
首先求出最短路径。我们用dp[i][j][k]表示当前三个部队分别位于i、j、k时的答案(j<=k<=i)。分别考虑从i、j、k中的一支部队走到i+1的情况,总共三个递推式。
对于返回,直接假设他们都走到最终状态后统一返回,就是从0到最终状态的最短路径就可以了。
哦对了,i要开滚动。
【错误点】
不要忘记滚动数组每次都要重新初始化!好像是第二次犯下这个错误了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 typedef long long ll; 8 const int MAXN=505; 9 int n,m; 10 int dis[MAXN][MAXN],dist[MAXN][MAXN]; 11 int dp[2][MAXN][MAXN]; 12 13 14 void init() 15 { 16 scanf("%d%d",&n,&m); 17 memset(dist,0x3f,sizeof(dist)); 18 for (int i=1;i<=m;i++) 19 { 20 int u,v,w; 21 scanf("%d%d%d",&u,&v,&w); 22 dist[u][v]=dist[v][u]=min(dist[u][v],w); 23 } 24 for (int i=0;i<=n;i++) dist[i][i]=0; 25 for(int k=0;k<=n;++k) 26 for(int i=0;i<=n;++i) 27 for(int j=0;j<=n;++j) 28 dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]); 29 } 30 31 void solve() 32 { 33 int cur=0; 34 memset(dp,0x3f,sizeof(dp)); 35 ll ans=1<<29; 36 dp[cur][0][0]=0; 37 for(int i=0;i<n;++i) 38 { 39 cur^=1; 40 memset(dp[cur],0x3f,sizeof(dp[cur]));//注意每次滚动数组都要清成无穷大,i=3的时候dp[0][0][0]!=0 41 for(int j=0;j<=i;++j) 42 for(int k=j;k<=i;++k) 43 { 44 dp[cur][j][k]=min(dp[cur][j][k],dp[1-cur][j][k]+dist[i+1][i]); 45 dp[cur][k][i]=min(dp[cur][k][i],dp[1-cur][j][k]+dist[j][i+1]); 46 dp[cur][j][i]=min(dp[cur][j][i],dp[1-cur][j][k]+dist[k][i+1]); 47 if (i==n-1) 48 { 49 ans=min(ans,(ll)dp[cur][j][k]+(ll)dist[0][n]+(ll)dist[0][j]+(ll)dist[0][k]); 50 ans=min(ans,(ll)dp[cur][k][i]+(ll)dist[0][n]+(ll)dist[0][k]+(ll)dist[0][i]); 51 ans=min(ans,(ll)dp[cur][j][i]+(ll)dist[0][n]+(ll)dist[0][j]+(ll)dist[0][i]); 52 } 53 } 54 } 55 cout<<ans<<endl; 56 } 57 58 int main() 59 { 60 init(); 61 solve(); 62 return 0; 63 }