uva 672 Gangsters( dp )


本文出自   http://blog.csdn.net/shuangde800



题目: 点击打开链接


题目大意

有个酒店的门会改变尺寸,变化范围是【0,k】,这个门每秒钟尺寸可以变大1,可以减小1,也可以不变。

现在有n个人,他们的尺寸为si,每个人在ti时刻想要进入酒店,只有在ti时刻酒店门的尺寸恰好和这个人的尺寸大小相等,这个人才可以进入。

每个人有一个值Pi,当某人进入酒店,酒店就会增加Pi值。

在[0,T]这段时间内(0秒时酒店的门尺寸状态是0),求让一些人进入酒店,使得总Pi值最大。




思路

开始时,以为同一时间两个人不能同时进入,结果WA了很久。 其实如果是同一时间,两个人的尺寸是相同的,门的状态也是相同的,那么两个人可以同时进入。


方法1:

先把所有人按照时间t从小到大排序。
首先,由题意可知,在t秒内,如果要从状态i到j,只有abs(i-j) <= t 才可行


f[i][j]表示: 前i个人,门状态为j时的最大值。


初始化f[0][1..K] = -1, f[0][0] = 0;

f[i][j] = max{ f[i-1][k]+P[i], 当f[i-1][k]!=-1 && 状态k->j可行}

如果j等于S[i],那么f[i][j]还要再加上P[i].


方法1代码:复杂度为O(n*k*k)

/**==========================================
 *   This is a solution for ACM/ICPC problem
 *
 *   @source:uva-672 Gangsters
 *   @type:  dp
 *   @author: shuangde
 *   @blog: blog.csdn.net/shuangde800
 *   @email: zengshuangde@gmail.com
 *===========================================*/
#include
  
   
#include
   
    
#include
    
     
#include
     
      
#include
      
       
#include
       
         #include
        
          using namespace std; typedef long long int64; const int INF = 0x3f3f3f3f; const double PI = acos(-1.0); const int MAXN = 110; int n, K, T; struct Node{ int t, p, s; bool operator < (const Node& rhs)const{ return t < rhs.t; } }arr[MAXN]; int f[MAXN][MAXN]; int main(){ int nCase; scanf("%d", &nCase); arr[0].t = arr[0].p = arr[0].s = 0; while(nCase--){ scanf("%d%d%d", &n, &K, &T); for(int i=1; i<=n; ++i) scanf("%d", &arr[i].t); for(int i=1; i<=n; ++i) scanf("%d", &arr[i].p); for(int i=1; i<=n; ++i) scanf("%d", &arr[i].s); sort(arr+1, arr+1+n); memset(f, -1, sizeof(f)); f[0][0] = 0; int ans = 0; for(int i=1; i<=n; ++i){ for(int j=0; j<=K; ++j){ for(int k=0; k<=K; ++k)if(f[i-1][k]!=-1 && abs(k-j) <= arr[i].t-arr[i-1].t){ if(j==arr[i].s && j){ f[i][j] = max(f[i][j], f[i-1][k]+arr[i].p); }else{ f[i][j] = max(f[i][j], f[i-1][k]); } ans = max(ans, f[i][j]); } } } printf("%d\n", ans); if(nCase) puts(""); } return 0; } 
        
       
      
     
    
   
  


方法2:

f[i]表示前i个人取得的最大值
f[i] = max{ f[j]+P[i],  0<=j<i && 第j个人可进入门 && 第j个人的状态到i的状态可达 } 


方法2代码:复杂度为O(n^2)

/**==========================================
 *   This is a solution for ACM/ICPC problem
 *
 *   @source:uva-672 Gangsters
 *   @type:  dp
 *   @author: shuangde
 *   @blog: blog.csdn.net/shuangde800
 *   @email: zengshuangde@gmail.com
 *===========================================*/
#include
  
   
#include
   
    
#include
    
     
#include
     
      
#include
      
       
#include
       
         #include
        
          using namespace std; typedef long long int64; const int INF = 0x3f3f3f3f; const double PI = acos(-1.0); const int MAXN = 110; int n, K, T; struct Node{ int t, p, s; bool operator < (const Node& rhs)const{ return t < rhs.t; } }arr[MAXN]; int f[MAXN]; bool check(int from, int to){ return abs(arr[from].s-arr[to].s) <= abs(arr[to].t - arr[from].t); } int main(){ int nCase; scanf("%d", &nCase); arr[0].t = arr[0].p = arr[0].s = 0; while(nCase--){ scanf("%d%d%d", &n, &K, &T); for(int i=1; i<=n; ++i) scanf("%d", &arr[i].t); for(int i=1; i<=n; ++i) scanf("%d", &arr[i].p); for(int i=1; i<=n; ++i) scanf("%d", &arr[i].s); sort(arr+1, arr+1+n); int ans = 0; memset(f, 0, sizeof(f)); for(int i=1; i<=n; ++i)if(arr[i].t){ for(int j=0; j
         
          =arr[j].p && check(j, i)){ f[i] = max(f[i], f[j]+arr[i].p); } ans = max(ans, f[i]); } printf("%d\n", ans); if(nCase) puts(""); } return 0; }
         
        
       
      
     
    
   
  






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值