题目连接http://icpc.ahu.edu.cn/OJ/Problem.aspx?id=543
乍一看,DP,但是规模太大 200*200*200*1000,然后想搜索剪枝,没有好的Idea
仔细想想,发现其实DP状态没有那么多,因为题目貌似隐含了,每次走只能往客户那边走,不能随便走,所以每次走过后,肯定有一个人的位置是确定的,就是在客户那儿,于是状态数就变成了200*200*1000,依然纠结能不能过~但是看到3s的限制,感觉差不多吧
dp[k][i][j] 表示第k个客户,另外两个人在i,j位置的最小花费。k用滚动数组压缩下。
保证i<j,但是依然不知道客户相对于i,j的位置,于是出现了下面代码中 大量的判断,以及代码copy冗余,看着都渗人。。
代码幸亏写的还算可以~~没出错~~不然根本改不出来~~大家瞅瞅就知道了~~
#include <stdio.h> #define INF 100000000 int N,L,ans; int c[205][205];//价值矩阵 int cal[1005];//请求序列 int dp[2][205][205]; void copy2(int a,int b) { int i,j; for (i=1;i<=L;++i) { for (j=1;j<=L;++j) { dp[b][i][j]=dp[a][i][j]; } } } void clr(int cur) { int i,j; for (i=1;i<=L;++i) { for (j=1;j<=L;++j) { dp[cur][i][j]=INF; } } } void work() { int i,j,cur,k,pre; //initial clr(0); cal[0]=1; dp[0][2][3]=0; //work for (k=1;k<=N;++k) { cur=k%2; pre=1-cur; //两次重叠,不需要移动 if (cal[k] == cal[k-1]) { copy2(pre,cur); continue; } //清理 clr(cur); //non for (i=1;i<=L;++i) { for (j=i+1;j<=L;++j) { if (dp[pre][i][j] == INF) continue; //状态不可达 if (i == cal[k-1] || j==cal[k-1]) continue; //错误状态,一开始忘记加,WA了一次 if (cal[k]==i) { if (j<cal[k-1] && dp[pre][i][j]<dp[cur][j][cal[k-1]]) { dp[cur][j][cal[k-1]]=dp[pre][i][j]; }else if (j>cal[k-1] && dp[pre][i][j]<dp[cur][cal[k-1]][j]) { dp[cur][j][cal[k-1]]=dp[pre][i][j]; } } if (cal[k]==j) { if (i<cal[k-1] && dp[pre][i][j]<dp[cur][i][cal[k-1]]) { dp[cur][i][cal[k-1]]=dp[pre][i][j]; }else if (i>cal[k-1] && dp[pre][i][j]<dp[cur][cal[k-1]][i]) { dp[cur][i][cal[k-1]]=dp[pre][i][j]; } } //other if (cal[k-1] < i) { if (dp[pre][i][j]+c[i][cal[k]] < dp[cur][cal[k-1]][j]) { dp[cur][cal[k-1]][j]=dp[pre][i][j]+c[i][cal[k]]; } if (dp[pre][i][j]+c[j][cal[k]] < dp[cur][cal[k-1]][i]) { dp[cur][cal[k-1]][i]=dp[pre][i][j]+c[j][cal[k]]; } if (dp[pre][i][j]+c[cal[k-1]][cal[k]] < dp[cur][i][j]) { dp[cur][i][j] = dp[pre][i][j]+c[cal[k-1]][cal[k]]; } }else if ( cal[k-1] < j) { if (dp[pre][i][j]+c[i][cal[k]] < dp[cur][cal[k-1]][j]) { dp[cur][cal[k-1]][j]=dp[pre][i][j]+c[i][cal[k]]; } if (dp[pre][i][j]+c[j][cal[k]] < dp[cur][i][cal[k-1]]) { dp[cur][i][cal[k-1]]=dp[pre][i][j]+c[j][cal[k]]; } if (dp[pre][i][j]+c[cal[k-1]][cal[k]] < dp[cur][i][j]) { dp[cur][i][j] = dp[pre][i][j]+c[cal[k-1]][cal[k]]; } }else { if (dp[pre][i][j]+c[i][cal[k]] < dp[cur][j][cal[k-1]]) { dp[cur][j][cal[k-1]]=dp[pre][i][j]+c[i][cal[k]]; } if (dp[pre][i][j]+c[j][cal[k]] < dp[cur][i][cal[k-1]]) { dp[cur][i][cal[k-1]]=dp[pre][i][j]+c[j][cal[k]]; } if (dp[pre][i][j]+c[cal[k-1]][cal[k]] < dp[cur][i][j]) { dp[cur][i][j] = dp[pre][i][j]+c[cal[k-1]][cal[k]]; } } } } } ans=INF; for (i=1;i<=L;++i) { for (j=1;j<=L;++j) { if (dp[cur][i][j] < ans) { ans=dp[cur][i][j]; } } } } int main() { int i,j; scanf("%d%d",&L,&N); for (i=1;i<=L;++i) { for (j=1;j<=L;++j) { scanf("%d",c[i]+j); } } for (i=1;i<=N;++i) { scanf("%d",cal+i); } work(); printf("%d",ans); }