链接
https://www.luogu.org/problemnew/show/P4046
https://www.luogu.org/problemnew/show/SP703
大意
一个公司有三个移动员,从一个点移到另一个点需要一定的代价,求满足所有要求的最小代价
思路
动态规划,按题意转移即可,我们可以利用滚动数组压缩空间
设 表示完成了前 个请求,其中一个员工上一次位于 ,这一次位于 ,另外两个员工位于 和 时的最小代价
代码(单组数据)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define r(i,a,b) for(register int i=a;i<=b;i++)
using namespace std;int n,m,a[1001],d[201][201],f[2][210][210],x,y,pre,now,ans=0x3f3f3f3f;
signed main()
{
scanf("%d",&n);
r(i,1,n) r(j,1,n) scanf("%d",&d[i][j]);
while(scanf("%d",&a[++m])!=EOF);m--;
memset(f,0x3f3f3f3f,sizeof(f));
f[0][1][2]=d[3][a[1]];
f[0][1][3]=d[2][a[1]];
f[0][2][3]=d[1][a[1]];
pre=1;now=0;
r(i,2,m)
{
pre^=1;now^=1;
memset(f[now],0x3f3f3f3f,sizeof(f[now]));
x=a[~-i];y=a[i];
r(u,1,n) if(u!=x)
r(v,1,n)
if(u!=v&&v!=x)
{
f[now][v][u]=f[now][u][v]=min(f[now][u][v],f[pre][u][v]+d[x][y]);
f[now][x][u]=f[now][u][x]=min(f[now][x][u],f[pre][u][v]+d[v][y]);
f[now][x][v]=f[now][v][x]=min(f[now][x][v],f[pre][u][v]+d[u][y]);
}
}
r(i,1,n) r(j,1,n)
if(i!=j&&i!=a[m]&&j!=a[m]) ans=min(ans,f[now][i][j]);
printf("%d",ans);
}
代码(多组数据)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define r(i,a,b) for(register int i=a;i<=b;i++)
using namespace std;int n,m,a[1001],d[201][201],f[2][210][210],x,y,pre,now,ans=0x3f3f3f3f,t;
signed main()
{
scanf("%d",&t);
while(t--)
{
memset(d,0,sizeof(d));
scanf("%d%d",&n,&m);
r(i,1,n) r(j,1,n) scanf("%d",&d[i][j]);
r(i,1,m) scanf("%d",a+i);
memset(f,0x3f3f3f3f,sizeof(f));
f[0][1][2]=d[3][a[1]];
f[0][1][3]=d[2][a[1]];
f[0][2][3]=d[1][a[1]];
pre=1;now=0;
r(i,2,m)
{
pre^=1;now^=1;
memset(f[now],0x3f3f3f3f,sizeof(f[now]));
x=a[~-i];y=a[i];
r(u,1,n) if(u!=x)
r(v,1,n)
if(u!=v&&v!=x)
{
f[now][v][u]=f[now][u][v]=min(f[now][u][v],f[pre][u][v]+d[x][y]);
f[now][x][u]=f[now][u][x]=min(f[now][x][u],f[pre][u][v]+d[v][y]);
f[now][x][v]=f[now][v][x]=min(f[now][x][v],f[pre][u][v]+d[u][y]);
}
}
ans=0x3f3f3f3f;
r(i,1,n) r(j,1,n)
if(i!=j&&i!=a[m]&&j!=a[m]) ans=min(ans,f[now][i][j]);
printf("%d\n",ans);
}
}