POJ 2184 Cow Exhibition (01背包)

题目大意:N个有两个属性Si、Fi的物品,从中选出几个使得sigma(Si) + sigma(Fi)最大,并且两者都必须是非负数.   比较好的一道题,考查对01背包的理解和运用能力. 对于这种一个物品两个属性的问题,即使没有什么体积或者价值那么明显的情况,我们也应该考虑一下01背包是否可行.其实 01背包不在于解决什么体积、价值问题,而在于这种动态规划的方法可以记录下来选择某些物品时,得到一个属性的值所对应的时刻另一个属性最优的状态.(这仅是我的拙见……) 那么显然我们就可以通过01背包来得到不同Si的值所对应能得到的Fi的最优值,然后通过枚举所有可能得到的Si值即可比较出最优解. 注意一点就是因为si[i]可能为负,所以范围要扩大一倍. 另外还需要注意对01背包第二层枚举顺序的理解:当si[i]>0时我们从大到小搜,当si[i]<0时从小到大搜.(理解不了的去看《背包九讲》吧~~)   (。。尼玛这题TLE+RE n次。。最后一看。。我们范围100000算成1000000了= =。。。捉鸡。。。  
#include 
 
   
    
  
#include 
  
    
      #include 
     
       #include 
      
        #include 
       
         #include 
        
          #include 
         
           #include 
          
            #include 
            #include 
            
              #include 
             
               #include 
              
                #define MID(x,y) ((x+y)>>1) using namespace std; typedef long long LL; int f[201010]; int si[110],fi[110]; int main(){ int n; int inf = - (1 << 30); scanf("%d", &n); for (int i = 0; i < n; i ++) scanf("%d%d", &si[i], &fi[i]); for (int i = 0; i < 201010; i ++) f[i] = inf; f[100000] = 0; for (int i = 0; i < n; i ++) if (si[i] < 0 && fi[i] < 0) continue; else if (si[i] > 0) for (int j = 200000; j >= si[i]; j --) if (f[j - si[i]] > inf) f[j] = max(f[j], f[j - si[i]] + fi[i]); else; else for (int j = si[i]; j <= 200000+si[i]; j ++) if (f[j - si[i]] > inf) f[j] = max(f[j], f[j - si[i]] + fi[i]); int ans = 0; for (int i = 100000; i <= 200000; i ++) if (f[i] >= 0 && i - 100000 + f[i] > ans) ans = i - 100000 + f[i]; printf("%d\n", ans); return 0; } 
               
              
             
           
          
         
        
       
      
    
 
   
 

你可能感兴趣的:(poj)