题意:
2<=L<=200
1<=N<=1000
题解:
一共就三个员工,我们可以在状态中记录三个员工的位置;
有:dp[i][x][y][z]:第i个工作完成后,三个员工的坐标分别是x,y,z,的最小花费
转移方程为:
dp[i+1][p[i]][y][z]=min(dp[i][x][y][z]+g[x][p[i+1]])
dp[i+1][x][p[i]][z]=min(dp[i][x][y][z]+g[y][p[i+1]])
dp[i+1][x][y][p[i]]=min(dp[i][x][y][z]+g[z][p[i+1]])
但是:L<=200,这样开数组的话,1000 * 200 * 200 * 200,直接爆了,所以不能这么大,我们要考虑节省空间,看看哪一维可以省略
我们想想,每次完成一个请求,是不是就应该有一个员工在这个位置p[i]上,而其他员工不变,所以我们可以用x,y表示本次不执行任务的两个员工位置,p[i]为执行任务的员工位置
这样dp[i][x][y]:第i个工作完成,未工作的员工位置是x,y,工作的员工位置是p[i],因为我们是顺序执行工作,相当于对于i,我们知道p[i-1]的位置,自然就知道上一次三个人的位置
这样转移方程为:
dp[i+1][x][y]=min(dp[i+1][x][y],dp[i][x][y]+g[p[i]][p[i+1]]);
dp[i+1][p[i]][y]=min(dp[i+1][p[i]][y],dp[i][x][y]+g[x][p[i+1]]);
dp[i+1][x][p[i]]=min(dp[i+1][x][p[i]],dp[i][x][y]+g[y][p[i+1]]);
代码:
代码不知道哪错了。。。
#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\n",a,b);
typedef long long ll;
using namespace std;
//Fe~Jozky
const ll INF_ll=1e18;
const int INF_int=0x3f3f3f3f;
inline ll read(){ll s=0,w=1ll;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w;
}
void rd_txt(){#ifdef ONLINE_JUDGE#elsefreopen("in.txt","r",stdin);#endif
}
const int maxn=200;
int g[maxn][maxn];
int p[1030];
int dp[1030][maxn][maxn];
int main()
{//rd_txt();int l,n;cin>>l>>n;for(int i=1;i<=l;i++){for(int j=1;j<=l;j++){cin>>g[i][j];}}p[0]=3;for(int i=1;i<=n;i++){cin>>p[i];}memset(dp,0x3f,sizeof(dp));dp[0][1][2]=0;for(int i=0;i<n;i++){for(int x=1;x<=l;x++){for(int y=1;y<=l;y++){if(x==y||x==p[i]||y==p[i])continue;dp[i+1][x][y]=min(dp[i+1][x][y],dp[i][x][y]+g[p[i]][p[i+1]]);dp[i+1][p[i]][y]=min(dp[i+1][p[i]][y],dp[i][x][y]+g[x][p[i+1]]);dp[i+1][x][p[i]]=min(dp[i+1][x][p[i]],dp[i][x][y]+g[y][p[i+1]]);} }}int minn=0x3f3f3f3f;for(int i=1;i<=l;i++){for(int j=1;j<=l;j++){if(i==j||i==p[n]||j==p[n])continue;minn=min(minn,dp[n][i][j]);}}cout<<minn;return 0;
}
AC代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>using namespace std;const int N = 210, M = 1010, INF = 0x3f3f3f3f;int n, m;
int w[N][N];
int f[M][N][N];
int p[M];int main()
{scanf("%d%d", &n, &m);for (int i = 1; i <= n; i ++ )for (int j = 1; j <= n; j ++ )scanf("%d", &w[i][j]);for (int i = 1; i <= m; i ++ ) scanf("%d", &p[i]);p[0] = 3;memset(f, 0x3f, sizeof f);f[0][1][2] = 0;for (int i = 0; i < m; i ++ )for (int x = 1; x <= n; x ++ )for (int y = 1; y <= n; y ++ ){int z = p[i], v = f[i][x][y];if (x == y || x == z || y == z) continue;int u = p[i + 1];f[i + 1][x][y] = min(f[i + 1][x][y], v + w[z][u]);f[i + 1][z][y] = min(f[i + 1][z][y], v + w[x][u]);f[i + 1][x][z] = min(f[i + 1][x][z], v + w[y][u]);}int res = INF;for (int x = 1; x <= n; x ++ )for (int y = 1; y <= n; y ++ ){int z = p[m];if (x == y || x == z || y == z) continue;res = min(res, f[m][x][y]);}printf("%d\n", res);return 0;
}