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. 移动服务的主要内容,如果未能解决你的问题,请参考以下文章

AcWing 274. 移动服务

《算法竞赛进阶指南》 0x50 动态规划

易语言数字指令编程大全(发送信息代码数据集合)

leetcode 274.H指数

AcWing 829. 模拟队列

AcWing 799. 最长连续不重复子序列