【hdu3080】01背包(容量10^7)

【hdu3080】01背包(容量10^7)

【题意】n个物品,有wi和vi,组成若干个联通块,只能选取一个联通块,问得到m的价值时最小要多少空间(v)。n<=50,v<=10^7

【题解】

先用并查集找出各个联通块。

这题主要就是v太大了,跟以往的背包不同。

我们回想01背包,f[j+v[i]]=max(f[j]+w[i]);

在这里面很明显很多状态都没有用。

优化:如果有2个状态,v1<=v2 && w1>=w2 则(v2,w2)这个状态是没有用的。

我们回到滚动数组中:

f[i][j+v[i]]=max(f[i^1][j]+w[i]);

那么我们可以用两个优先队列,q0存以前的f[i-1],q1存当前的f[i]。

我们在求f[i]的时候,就把q0一个个pop出来,更新后放到q1里面去。

做完i,我们要把q1放到q0,然后做i+1。

在把q1放到q0的时候就把没用的状态去掉(对于(v,val),先按val从大到小排序,再按v从小到大排序,对同样的val取最小的v)。

 

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<vector>
 8 using namespace std;
 9 
10 typedef long long LL;
11 const LL N=60,INF=(LL)1e15;
12 LL n,m,fa[N],t[N],w[N],c[N][N];
13 struct node{LL v,val;};
14 
15 struct cmp
16 {
17     bool operator () (node &x,node &y)
18     {
19         if(x.val==y.val) return x.v<y.v;
20         return x.val<y.val;
21     }
22 };
23 
24 priority_queue<node,vector<node>,cmp> q0,q1;
25 
26 LL findfa(LL x)
27 {
28     if(fa[x]==x) return x;
29     return findfa(fa[x]);
30 }
31 
32 LL minn(LL x,LL y){return x<y ? x:y;}
33 
34 int main()
35 {
36     freopen("a.in","r",stdin);
37     freopen("me.out","w",stdout);
38     int T,cas=0;
39     scanf("%d",&T);
40     while(T--)
41     {
42         scanf("%d%d",&n,&m);
43         for(int i=1;i<=n;i++) fa[i]=i;
44         for(int i=1;i<=n;i++)
45         {
46             int num,xx;
47             scanf("%lld%lld%d",&t[i],&w[i],&num);
48             for(int j=1;j<=num;j++)
49             {
50                 scanf("%d",&xx);
51                 fa[findfa(i)]=findfa(xx);
52             }
53         }
54         memset(c,0,sizeof(c));
55         for(int i=1;i<=n;i++)
56         {
57             fa[i]=findfa(i);
58             c[fa[i]][++c[fa[i]][0]]=i;
59         }
60         node x,p,f;
61         LL ans=INF;
62         for(int k=1;k<=n;k++) if(c[k][0])
63         {
64             // printf("k = %d\n",k);
65             while(!q0.empty()) q0.pop();
66             while(!q1.empty()) q1.pop();
67             x.v=0;x.val=0;
68             q0.push(x);
69             for(int j=1;j<=c[k][0];j++)
70             {
71                 int i=c[k][j];
72                 while(!q0.empty())
73                 {
74                     x=q0.top();q0.pop();q1.push(x);
75                     f.v=x.v+t[i];
76                     f.val=x.val+w[i];
77                     if(f.v>=ans) continue;
78                     if(f.val>=m) {ans=minn(ans,f.v);continue;}
79                     q1.push(f);
80                 }
81                 LL mn=INF;
82                 while(!q1.empty()) 
83                 {
84                     x=q1.top();q1.pop();
85                     if(x.val>=m) ans=minn(ans,x.v);
86                     if(x.v<mn) mn=x.v,q0.push(x);
87                     // printf("v = %lld  val = %lld\n",x.v,x.val);
88                 }
89             }
90             // f[i^1][v+c[i]]=maxx(f[i^1][v+c[i]],f[i][v]+w[i]]);
91         }
92         if(ans<INF) printf("Case %d: %lld\n",++cas,ans);
93         else printf("Case %d: Poor Magina, you can't save the world all the time!\n",++cas);
94     }
95     return 0;
96 }

 

posted @ 2016-10-17 21:18 拦路雨偏似雪花 阅读( ...) 评论( ...) 编辑 收藏
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值