AcWing274.移动服务

题目描述

一个公司有三个移动服务员,最初分别在位置1,2,3处。

如果某个位置(用一个整数表示)有一个请求,那么公司必须指派某名员工赶到那个地方去。

某一时刻只有一个员工能移动,且不允许在同样的位置出现两个员工。

从 p 到 q 移动一个员工,需要花费 c(p,q)。

这个函数不一定对称,但保证 c(p,p)=0。

给出N个请求,请求发生的位置分别为 p1~pN。

公司必须按顺序依次满足所有请求,目标是最小化公司花费,请你帮忙计算这个最小花费。

输入格式
第1行有两个整数L,N,其中L是位置数量,N是请求数量,每个位置从1到L编号。

第2至L+1行每行包含L个非负整数,第i+1行的第j个数表示c(i,j) ,并且它小于2000。

最后一行包含N个整数,是请求列表。

一开始三个服务员分别在位置1,2,3。

输出格式
输出一个整数M,表示最小花费。

数据范围
3≤L≤200,
1≤N≤1000
输入样例:
5 9
0 1 1 1 1
1 0 2 3 2
1 1 0 4 1
2 1 5 0 1
4 2 3 4 0
4 2 4 1 5 4 3 2 1
输出样例:
5
---
思路如下:
DP的状态为已经完成的请求数量,通过指派一位服务员
可以把"完成i - 1个请求的状态"转移到"完成i个请求的状态"
那么我们可以知道转移从dp[i - 1] -> dp[i]
dp[i][x][y][z] 代表为第i次选择的情况下,对应的1,2,3号服务员
所对应的位置
那么可以得知
dp[i][arr[i]][y][z] = min(dp[i][arr[i]][y][z], dp[i - 1][x][y][z] + cost[x][arr[i]])
dp[i][x][arr[i]][z] = min(dp[i][x][arr[i]][z], dp[i - 1][x][y][z] + cost[y][arr[i]])
dp[i][x][y][arr[i]] = min(dp[i][x][y][arr[i]], dp[i - 1][x][y][z] + cost[z][arr[i]])

因为肯定有一个位置,继承了上一个的位置
所以保存两个状态就可以了

三种状态转移 pi,x,y
dp[i][x][y] = min(dp[i][x][y], dp[i - 1][x][y] + cost[pi - 1][pi])
dp[i][pi][y] = min(dp[i][pi][y], dp[i - 1][x][y] + cost[x][pi])
dp[i][x][pi] = min(dp[i][x][pi], dp[i - 1][x][y] + cost[y][pi])

dp[0][1][2] = 0;
for(int i = 1; i <= n; i ++)
{
for(int x = 1; x <= l; x ++)
{
for(int y = 1; y <= l; y ++)
{
if(x == y || x == arr[i] || y == arr[i])continue;
dp[i][x][y] = min(dp[i][x][y], dp[i - 1][x][y] + cost[temp][arr[i]]);
dp[i][pi][y] = min(dp[i][pi][y], dp[i - 1][x][y] + cost[x][pi]);
dp[i][x][pi] = min(dp[i][x][pi], dp[i - 1][x][y] + cost[y][pi]);
}
}
}


代码如下:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 205;
int cost[MAXN][MAXN];
int arr[MAXN * 5];
int dp[1005][MAXN][MAXN];
typedef long long ll;
int l, n;
int main(){
    scanf("%d%d", &l, &n);
    for(int i = 1; i <= l; i ++){
        for(int j = 1; j <= l; j ++){
            scanf("%d", &cost[i][j]);
        }
    }
    for(int i = 1; i <= n; i ++){
        scanf("%d", &arr[i]);
    }
    arr[0] = 3;
    for(int i = 0; i <= n; i ++){
        for(int j = 1; j <= l; j ++){
            for(int z = 1; z <= l; z ++){
                dp[i][j][z] = 0x3f3f3f3f;
            }
        }
    }
    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 == arr[i] || y == arr[i]) continue;
                dp[i + 1][x][y] = min(dp[i + 1][x][y], dp[i][x][y] + cost[arr[i]][arr[i + 1]]);
                dp[i + 1][arr[i]][y] = min(dp[i + 1][arr[i]][y], dp[i][x][y] + cost[x][arr[i + 1]]);
                dp[i + 1][x][arr[i]] = min(dp[i + 1][x][arr[i]], dp[i][x][y] + cost[y][arr[i + 1]]);
            }
        }
    }
    int re = 0x7fffffff;
    for(int x = 1; x <= l; x ++){
        for(int y = 1; y <= l; y ++){
            re = min(re, dp[n][x][y]);
        }
    }
    printf("%d\n", re);
    return 0;
}

AcWing274.移动服务

上一篇:常用的Python代码段


下一篇:anyproxy学习1-windows平台安装和抓手机app上https请求