zoukankan      html  css  js  c++  java
  • SP703 SERVICE

    
    

    题意翻译

    
    

    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 } 
  • 相关阅读:
    Linux Window Redis安装
    Mysql 死锁的详细分析方法
    mariadb rpm 安装
    我希望我能做到:我只是认真--做技术的人,对待技术,应该拥有什么样的态度?
    Google140道面试题
    mysql my.cnf配置文件详解
    Linux iostat字段解析
    Linux mpstat字段解析
    Selenium入门8 js调用
    Selenium入门7 内嵌框架iframe
  • 原文地址:https://www.cnblogs.com/DarkValkyrie/p/11053352.html
Copyright © 2011-2022 走看看