題目連接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);
}