AcWing 274. 移动服务
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AcWing 274. 移动服务相关的知识,希望对你有一定的参考价值。
题意:
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
#else
freopen("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;
}
以上是关于AcWing 274. 移动服务的主要内容,如果未能解决你的问题,请参考以下文章