poj 2184

背包问题!!!

WA。。。。。。。。无语了!!!!(搜索做的,就是过不了)

#include<iostream>
#include<string.h>
#include<queue>
#include<stdio.h>
#include<algorithm>
using namespace std;
queue<int> m;
struct node{int s,f;}a[105];
int sum=0,maxn=0,ts=0,tf=0;

bool com(node x,node y){if(x.s!=y.s) return x.s>y.s;
else
return x.f>y.f;
}
int main(){
 //freopen("in.txt","r",stdin);
 //freopen("out.txt","w",stdout);
 int n;
 cin>>n;

 maxn=0;sum=0;
 int k=n;
 for(int i=0;i<n;i++) cin>>a[i].s>>a[i].f;
 sort(a,a+n,com);
 //for(int i=0;i<n;i++) cout<<a[i].s<<endl;
  for(int i=0;i<n;i++) if(a[i].s<0&&a[i].f<0){ k=i;break;}
 //cout<<k<<endl;
 for(int i=0;i<(1<<k);i++)
  {
   while(!m.empty())m.pop();
   sum=0;ts=0;tf=0;
   for(int j=0;j<k;j++){
    if(i&(1<<j)) m.push(j);
    }
    int x;
   while(!m.empty()){x=m.front();tf+=a[x].f;ts+=a[x].s;sum=sum+a[x].f+a[x].s;m.pop();} 
  if(ts>=0&&tf>=0)if(sum>maxn) maxn=sum;
  }
  
   cout<<maxn<<endl;
 system("pause");
 return 0;}

 

------------------------------------------------------------------------------------------------

(0,1)背包的变形,但变得可真厉害,我是开别人的代码好久才弄明白的;

 把s看成是背包容量,f看成是价值,

#include<iostream>
#include<string.h>
#define MID 100000
using namespace std;
int vis[200005];//visited[i+MID]标记左边的数能否组成i
int dp[200005];//dp[i+MID]总的s值为i时的最优的f值(其实就是说两个都是和的形式)


int main(){
 int n;
  cin>>n;
 memset(vis,0,sizeof(vis));
 vis[MID]=1;
 int _min=0,_max=0;
 for(int i=0;i<200005;i++) dp[i]=-0xffff;
 dp[MID]=0;
 int s,f;
 for(int j=0;j<n;j++){
  cin>>s>>f;

 


  if(s<=0&&f<=0) continue;//剪支;只有一个小于或等于0不能被剪

 


  if(s>0){//如果s<0则从小到大,否则从大到小扫描,避免把同一个数加两次。
   for(int i=_max;i>=_min;i--){
    if(vis[MID+i]) if(dp[MID+i+s]<dp[MID+i]+f)
     {dp[MID+i+s]=dp[MID+i]+f;vis[MID+i+s]=1;}
     }
   _max+=s;
  
  }

 


  else{
   for(int i=_min;i<=_max;i++)
    if(vis[MID+i]) if(dp[MID+i+s]<dp[MID+i]+f)
    {dp[MID+i+s]=dp[MID+i]+f;vis[MID+i+s]=1;
    }
   _min+=s;
    }

 


    }
    int rez=0;
    
  for(int i=0;i<=_max;i++)//剪掉了i<0的情况
   if(vis[i+MID])
   if(dp[i+MID]>=0&&dp[i+MID]+i>rez)
    rez=i+dp[i+MID];
    
  cout<<rez<<endl;
  
  
 return 0;}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值