题意翻译


Description   一个公司有三个移动服务员。如果某个地方有一个请求,某个员工必须赶到那个地方去(那个地方没有其他员工),某一时刻只有一个员工能移动。只有被请求后,他才能移动,不允许在同样的位置出现两个员工。从位置P到Q移动一个员工的费用是C(P, Q)。这个函数没有必要对称,但是C(P, P) = 0。一开始三个服务员分别在位置1,2,3,公司必须满足所有的请求。 目标是最小化公司的费用。 Input   第1行:2个整数L,N(3<=L<=200, 1<=N<=1000). L是位置数,每个位置从1到L编号,N是请求数。   接下来L行,每行包含L个非负整数,第i+1行的第j个数表示C(i, j),并且它小于2000.   最后一行包含N个数,是请求列表。 Output    第1行:一个数M,表示最小的服务花费


输入输出样例


输入样例#1:

1
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
输出样例#1:

5

解析:

这题值得好好理解。是我滚动数组入门题目。

容易想到以当前的请求作为阶段,当前服务员所在位置的最小花费作为状态。
首先,
四维数组会爆空间。不用滚动数组也会爆空间。。。 我们假设dp[i][x][y]表示在第i个请求时,有一个服务员在x位置,一个服务员在y位置。如果x和y都不在上一个请求所在位置,那么剩下那个服务员必定在上一个请求的位置那里。 我们有三种决策:
  • 将上一个请求位置的服务员转移到当前请求的位置上,前提是x和y都不在上一个请求所在位置;
  • 将x处的服务员转移到当前请求的位置上,前提是y处的服务员不在当前请求的位置上(注意:上一个请求位置上的服务员不可能在此处了,不需要此条件);
  • 将y处的服务员转移到当前请求的位置上,前提是x处的服务员不在当前请求的位置上;

我们很容易设计状态转移方程:

if(x!=p[i]&&y!=p[i])
dp[now][x][y]=min(dp[now][x][y],dp[now^][x][y]+a[p[i-]][p[i]]);
if(y!=p[i])
dp[now][p[i-]][y]=min(dp[now][p[i-]][y],dp[now^][x][y]+a[x][p[i]]);
if(x!=p[i])
dp[now][x][p[i-]]=min(dp[now][x][p[i-]],dp[now^][x][y]+a[y][p[i]]);

当然,这些方程都有一个大前提,就是当前请求的x和y既不能在同一个位置上,又不能在上一个请求的位置上(注意细节)。

最后,我们检查一遍最后一个请求时的状态,找出最小值就OK了。

参考代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 201
#define MOD 2520
#define E 1e-12
#define ri register int
using namespace std;
int a[N][N],dp[][N][N],p[];
inline int read()
{
int f=,x=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int main()
{
int t;
cin>>t;
while(t--)
{
memset(a,,sizeof(a));
memset(p,,sizeof(p));
int now=,l,n;
l=read(),n=read();
for(ri i=;i<=l;i++)
for(ri j=;j<=l;j++) a[i][j]=read();
for(ri i=;i<=n;i++) p[i]=read();
memset(dp[now],0x3f,sizeof(dp));
p[]=;dp[][][]=;
for(ri i=;i<=n;i++){
now^=;//滚动数组
memset(dp[now],0x3f,sizeof(dp[now]));
for(ri x=;x<=l;x++)//有l个地方可以去
if(x!=p[i-])
for(ri y=;y<=l;y++)
{
if(x==y&&y==p[i-]) continue;
if(x!=p[i]&&y!=p[i])
dp[now][x][y]=min(dp[now][x][y],dp[now^][x][y]+a[p[i-]][p[i]]);
if(y!=p[i])
dp[now][p[i-]][y]=min(dp[now][p[i-]][y],dp[now^][x][y]+a[x][p[i]]);
if(x!=p[i])
dp[now][x][p[i-]]=min(dp[now][x][p[i-]],dp[now^][x][y]+a[y][p[i]]);
}
}
int ans=INF;
for(ri i=;i<=l;i++)
for(ri j=;j<=l;j++)
if(i!=j&&i!=p[n]&&j!=p[n])
ans=min(ans,dp[now][i][j]);//另一个人在p[n]处
cout<<ans<<endl;
}
return ;
}

SP703 SERVICE - Mobile Service[DP]的更多相关文章

  1. SP703 SERVICE - Mobile Service

    思路:DP 提交:1次 题解: 我们把处理到的要求作为阶段. \(f[i][x][y][z]\)表示第 \(i\) 个要求,三个人分别的位置. 发现这样有很多无用状态,因为显然在第 \(i\) 个要求 ...

  2. SPOJ 703 SERVICE - Mobile Service 题解

    题面 好题啊!~ 设f[i][j][k][l]表示已经处理完前i个请求后,a在j,b在k,c在l的最小值是多少: 那么f[i][p[i]][k][l]=min(f[i][p[i]][k][l],f[i ...

  3. CH5102 Mobile Service【线性dp】

    5102 Mobile Service 0x50「动态规划」例题 描述 一个公司有三个移动服务员,最初分别在位置1,2,3处.如果某个位置(用一个整数表示)有一个请求,那么公司必须指派某名员工赶到那个 ...

  4. CH 5102 Mobile Service(线性DP)

    CH 5102 Mobile Service \(solution:\) 这道题很容易想到DP,因为题目里已经说了要按顺序完成这些请求.所以我们可以线性DP,但是这一题的状态不是很好设,因为数据范围有 ...

  5. CH5102 Mobile Service

    CH5102 Mobile Service 描述 一个公司有三个移动服务员,最初分别在位置1,2,3处.如果某个位置(用一个整数表示)有一个请求,那么公司必须指派某名员工赶到那个地方去.某一时刻只有一 ...

  6. TYVJ1061 Mobile Service

    P1061 Mobile Service 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 一个公司有三个移动服务员.如果某个地方有一个请求,某个员工必须赶到那 ...

  7. Unable to create Azure Mobile Service: Error 500

    I had to go into my existing azure sql database server and under the configuration tab select " ...

  8. 如何使用新浪微博账户进行应用登录验证(基于Windows Azure Mobile Service 集成登录验证)

    使用三方账号登录应用应该对大家来说已经不是什么新鲜事儿了,但是今天为什么还要在这里跟大家聊这个话题呢,原因很简单 Windows Azure Mobiles Service Authenticatio ...

  9. vs2015-Azure Mobile Service

    /App_Data /App_Start/ WebApiConfig.cs using System; using System.Collections.Generic; using System.C ...

随机推荐

  1. 高级UI-Palette

    Google推出的Palette是用来调色的,正如其汉语意思一样,可以用来显示颜色,在显示图片的时候,会配合图片的色调来显示,这样就显得很融合,其实Palette可以分析出图片中的很多特性,例如主色调 ...

  2. 【转】git2.9.2使用总结

    git2.9.2使用总结 1.系统:Windows7 2.git版本:2.9.2 由于我的git版本是最新版,后面我出现的坑就是最新版本的问题. 3.托管环境:开源中国的码云 . 使用步骤 1.在码云 ...

  3. Linux由于物理节点故障导致的异常重启-Case1

    问题描述:Linux VM异常重启,需要排查问题原因 排查结果: 查询Messages日志获取到的信息 虚拟机内核版本: Jun :: test01 kernel: Linux version -.e ...

  4. 路由器04--OPKG

    1.简介 https://oldwiki.archive.openwrt.org/doc/techref/opkg Opkg 是一个基于 ipkg 的轻量级的软件包管理系统,主要用于嵌入式系统,目前应 ...

  5. SQLServer 查询view中是否包含某个关键字

    在数据库view的创建中,会遇到一些跨数据库的view脚本,但是在将view更新到production的时候可能忘记更改database name,导致出现一些问题. 以下脚本可以检查出包含某个关键字 ...

  6. 【洛谷】P3980 [NOI2008]志愿者招募

    [洛谷]P3980 [NOI2008]志愿者招募 我居然现在才会用费用流解线性规划-- 当然这里解决的一类问题比较特殊 以式子作为点,变量作为边,然后要求就是变量在不同的式子里出现了两次,系数一次为+ ...

  7. WIN10更换无线网卡后WIFI无法正常启用

    这里根据自己经历提供几个方案: 首先我们要确定这两个地方正常(表示网卡能识别.驱动安装好:有无线开关没打开的朋友请出门右转): 方案一:万能的重启,不觉得麻烦的就多重启几遍.大力出奇迹! 方案二:然后 ...

  8. Html大段文本自适应换行显示-SSM

    只处理前端: <style> .ctl{ table-layout:fixed } .ctl td{ word-break:break-all } </style> <d ...

  9. linux破解navicat for mysql

    第一次执行start_navicat时,会在用户主目录下生成一个名为.navicat64的隐藏文件夹. cd ~/.navicat64 此文件夹下有一个system.reg文件 rm system.r ...

  10. Java中将字符串用空格分割成字符串数组的split方法

    官方文档链接:public String[] split(String regex) 本文以空格作为分割串. CaseOne import java.util.Scanner; public clas ...