【线性dp && 蓝书刷题】 Mobile Service

题目传送门

题目描述:

一个公司有三个移动服务员。如果某个地方有一个请求,某个员工必须赶到那个地方去(那个地方没有其他员工),某一时刻只有一个员工能移动。被请求后,他才能移动,不允许在同样的位置出现两个员工。从p到q移动一个员工,需要花费c(p,q)。这个函数没有必要对称,但是c(p,p)=0。公司必须满足所有的请求。目标是最小化公司花费。

c[i][j] 由题目输入给出


分析:

在第一反应下,我们不难想出以下状态:
f [ i ] [ x ] [ y ] [ z ] i x , y , z f[i][x][y][z] 表示完成了前i个请求,三个员工分别位于 x,y,z 位置的最小花费

我们可以考虑 用 阶段 i-1 来更新当前状态。
那么方程十分显然 ,这里不再说。

考虑优化
由于我们可以确定在进行第i个任务时,第i-1个任务已经完成,也就是说肯定有一个人在p[i-1]这个位置上,根据这个特性,我们可以优化空间:
f [ i ] [ x ] [ y ] i x , y f[i][x][y] 表示完成了前i个请求,其他两个员工位于 x,y 位置的最小花费
根据第三个人的位置是p[i-1],我们可以列出一下方程:
f [ i ] [ j ] [ k ] = f [ i ] [ k ] [ j ] = m i n ( f [ i ] [ j ] [ k ] , f [ i 1 ] [ j ] [ k ] + c [ p [ i 1 ] ] [ p [ i ] ] ) ; 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 ] ] = m i n ( f [ i ] [ p [ i 1 ] ] [ j ] , f [ i 1 ] [ j ] [ k ] + c [ k ] [ 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 ] ] = m i n ( f [ i ] [ p [ i 1 ] ] [ k ] , f [ i 1 ] [ j ] [ k ] + c [ j ] [ 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]]);


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;
}

猜你喜欢

转载自blog.csdn.net/huang_ke_hai/article/details/90604624