SP703 SERVICE - Mobile Service[DP]


题意翻译


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^1][x][y]+a[p[i-1]][p[i]]);
if(y!=p[i])
    dp[now][p[i-1]][y]=min(dp[now][p[i-1]][y],dp[now^1][x][y]+a[x][p[i]]);
if(x!=p[i])
    dp[now][x][p[i-1]]=min(dp[now][x][p[i-1]],dp[now^1][x][y]+a[y][p[i]]);

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

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

参考代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<string>
 7 #include<cstdlib>
 8 #include<queue>
 9 #include<vector>
10 #define INF 0x3f3f3f3f
11 #define PI acos(-1.0)
12 #define N 201
13 #define MOD 2520
14 #define E 1e-12
15 #define ri register int
16 using namespace std;
17 int a[N][N],dp[2][N][N],p[1001];
18 inline int read()
19 {
20     int f=1,x=0;char c=getchar();
21     while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
22     while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
23     return x*f;
24 }
25 int main()
26 {
27     int t;
28     cin>>t;
29     while(t--)
30     {
31         memset(a,0,sizeof(a));
32         memset(p,0,sizeof(p));
33         int now=0,l,n;
34         l=read(),n=read();
35         for(ri i=1;i<=l;i++)
36          for(ri j=1;j<=l;j++) a[i][j]=read();
37         for(ri i=1;i<=n;i++) p[i]=read();
38         memset(dp[now],0x3f,sizeof(dp));
39         p[0]=3;dp[0][1][2]=0;
40         for(ri i=1;i<=n;i++){
41             now^=1;//滚动数组
42             memset(dp[now],0x3f,sizeof(dp[now]));
43             for(ri x=1;x<=l;x++)//有l个地方可以去
44                 if(x!=p[i-1])
45                     for(ri y=1;y<=l;y++)
46                     {
47                         if(x==y&&y==p[i-1]) continue;
48                         if(x!=p[i]&&y!=p[i])
49                             dp[now][x][y]=min(dp[now][x][y],dp[now^1][x][y]+a[p[i-1]][p[i]]);
50                         if(y!=p[i])
51                             dp[now][p[i-1]][y]=min(dp[now][p[i-1]][y],dp[now^1][x][y]+a[x][p[i]]);
52                         if(x!=p[i])
53                             dp[now][x][p[i-1]]=min(dp[now][x][p[i-1]],dp[now^1][x][y]+a[y][p[i]]);
54                     }
55         }
56         int ans=INF;
57         for(ri i=1;i<=l;i++)
58          for(ri j=1;j<=l;j++)
59           if(i!=j&&i!=p[n]&&j!=p[n])
60             ans=min(ans,dp[now][i][j]);//另一个人在p[n]处
61         cout<<ans<<endl;
62     }
63     return 0;
64 } 

原文地址:https://www.cnblogs.com/DarkValkyrie/p/11053352.html

时间: 2024-11-14 12:51:43

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

SP703 SERVICE - Mobile Service

思路:DP 提交:1次 题解: 我们把处理到的要求作为阶段. \(f[i][x][y][z]\)表示第 \(i\) 个要求,三个人分别的位置. 发现这样有很多无用状态,因为显然在第 \(i\) 个要求后,总有一个人在 \(pos[i]\) 所以我们省掉一维. 注意第一维要滚动. 代码: #include<bits/stdc++.h> #define R register int using namespace std; namespace Luitaryi { inline int g() {

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-1][j][k][l]+c(j,p[i])); f[i][j][p[i]][l]=min(f[i][j][p[i]][l],f[i-1][j][k][l]+c(k,p[i])); f[i][j][k][p[i]]=min(f[i][j][k][p[i]],f[i-1][j][k][l]+c(l,p

CH5102 Mobile Service【线性dp】

5102 Mobile Service 0x50「动态规划」例题 描述 一个公司有三个移动服务员,最初分别在位置1,2,3处.如果某个位置(用一个整数表示)有一个请求,那么公司必须指派某名员工赶到那个地方去.某一时刻只有一个员工能移动,且不允许在同样的位置出现两个员工.从 p 到 q 移动一个员工,需要花费 c(p,q).这个函数不一定对称,但保证 c(p,p)=0.给出N个请求,请求发生的位置分别为 p_1~p_N.公司必须按顺序依次满足所有请求,目标是最小化公司花费,请你帮忙计算这个最小花费

Mobile Service

Mobile Service 有一\(1\times L\)的网格,3个人初始在1,2,3,给出从每个位置i移到另一个位置j的费用\(c[i][j]\),并且保证两个人不在同一位置,再给出n个请求,第i个请求记做\(p_i\),要求有一个人到达位置\(p_i\),问按先后顺序完成这些请求的最小费用,\(3<=L<=200, 1<=N<=1000\). 解 显然要表现出这是第几个请求,且要知道3个人的位置才能转移,故设\(f[i][j][k][l]\)表示第i个请求,位置分别在j,k

Windows Azure之Mobile Service

我建个android app和Windows Azure的Mobile Service配合,以实现会员注册的功能,实际十分简单,微软家的东西真心好用 首先新建个Mobile Service New->Mobile Service->Create之后弹出下图的对话框 URL就自定义一个,如果有人注册了会报错,换个就好,database新建还是使用已存在的都可以,新建之后会多一步让你输入要新建的数据库的名称和密码,backend就选Javascript,点击箭头下一步 使用现存的会让你输入密码,建

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 "yes" to allow azure services to access the server. Note: this is the configuration for the server not the database. Once I did this, I tried again to

windows phone开发-windows azure mobile service使用入门

在使用azure之前,我一直只能做本地app,或者使用第三方提供的api,尽管大多数情况下够用,但是仍不能随心所欲操纵数据,这种感觉不是特别好.于是在azure发布后,我就尝试使用azure来做为个人数据中心,可选的方式有很多,但今天我给大家介绍的是azure mobile service. 1.创建Mobile Service Azure中创建Mobile Service很简单,与创建其他项目类似,流程如下: i. ii. iii. ii 这里我使用的是Windows Azure国际版,经过简

Windows Azure Mobile Service - Logs for diagnostics

If you get stuck on client side Mobile Service error and the error message is less useful, try to see the Logs tab in your Azure Mobile Service, you probably can get the useful information from the log reference: http://stackoverflow.com/questions/18

[TYVJ1061] Mobile Service|动态规划|滚动数组

P1061 Mobile Service 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 一个公司有三个移动服务员.如果某个地方有一个请求,某个员工必须赶到那个地方去(那个地方没有其他员工),某一时刻只有一个员工能移动.被请求后,他才能移动,不允许在同样的位置出现两个员工.从p到q移动一个员工,需要花费c(p,q).这个函数没有必要对称,但是c(p,p)=0.公司必须满足所有的请求.目标是最小化公司花费. 输入格式 第一行有两个整数L,N(3<=L<=