题目传送门
题目描述:
一个公司有三个移动服务员。如果某个地方有一个请求,某个员工必须赶到那个地方去(那个地方没有其他员工),某一时刻只有一个员工能移动。被请求后,他才能移动,不允许在同样的位置出现两个员工。从p到q移动一个员工,需要花费c(p,q)。这个函数没有必要对称,但是c(p,p)=0。公司必须满足所有的请求。目标是最小化公司花费。
c[i][j] 由题目输入给出
分析:
在第一反应下,我们不难想出以下状态:
我们可以考虑 用 阶段 i-1 来更新当前状态。
那么方程十分显然 ,这里不再说。
考虑优化
由于我们可以确定在进行第i个任务时,第i-1个任务已经完成,也就是说肯定有一个人在p[i-1]这个位置上,根据这个特性,我们可以优化空间:
设
根据第三个人的位置是p[i-1],我们可以列出一下方程:
Code
#include<bits/stdc++.h>
using namespace std;
int n,l;
int minn=1000000000;
int p[1010];
int c[1010][1010];
int f[1010][201][201];
int main(){
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
scanf("%d %d",&l,&n);
for (int i=1;i<=l;i++)
for (int j=1;j<=l;j++)
scanf("%d",&c[i][j]);
p[0]=3;
memset(f,20,sizeof(f));
f[0][1][2]=0;
for (int i=1;i<=n;i++) scanf("%d",&p[i]);
for (int i=1;i<=n;i++){
for (int j=1;j<=200;j++)
for (int k=1;k<=200;k++){
if (j==k || j==p[i-1] || k==p[i-1]) continue;
f[i][j][k]=f[i][k][j]=min(f[i][j][k],f[i-1][j][k]+c[p[i-1]][p[i]]);
f[i][p[i-1]][j]=f[i][j][p[i-1]]=min(f[i][p[i-1]][j],f[i-1][j][k]+c[k][p[i]]);
f[i][p[i-1]][k]=f[i][k][p[i-1]]=min(f[i][p[i-1]][k],f[i-1][j][k]+c[j][p[i]]);
if (i==n) minn=min(minn,min(f[i][j][k],min(f[i][p[i-1]][j],f[i][p[i-1]][k])));
}
}
printf("%d",minn);
return 0;
}