CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。
1514: Packs
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 61 Solved: 4
[Submit][Status][Web Board]
Description
Give
you n packs, each of it has a value v and a weight w. Now you should
find some packs, and the total of these value is max, total of these
weight is equal to m.
Input
First line is a number T( T ≤ 5) represent the test cases.
Then for each set of cases, first line is n (1 ≤ n ≤ 40) and m (1 ≤ m
< 2^31), follow n line each is Wi (1 ≤ Wi < 2^31) and Vi (-2^31
< Vi < 2^31).
Output
Each case a line for max value.(Each set of inputs to ensure the solvability)
Sample Input
2
3 3
1 1
2 2
3 4
5 2
1 -5
1 -8
1 0
1 -2
1 5
Sample Output
4
5 注意:这里要求是满足总重量必须固定,而不是接近总重量。这就成了直接折半枚举,map大法就行了。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long LL;
const long long INF=99999999999999999LL;
const int EXP=1e-;
const int MS=; map<LL,LL> mp;
int n;
LL W; LL w[MS],v[MS]; void solve()
{
mp.clear();
int n1=n/;
for(int i=;i<(<<n1);i++)
{
LL sw=,sv=;
for(int j=;j<n1;j++)
{
if((i>>j)&)
{
sw+=w[j];
sv+=v[j];
}
}
mp[sw]=max(mp[sw],sv);
}
LL ans=-INF;
for(int i=;i< <<(n-n1);i++)
{
LL sw=,sv=;
for(int j=;j<(n-n1);j++)
{
if((i>>j)&)
{
sw+=w[n1+j];
sv+=v[n1+j];
}
}
if(mp.count(W-sw))
ans=max(ans,mp[W-sw]+sv);
}
printf("%lld\n",ans);
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%lld",&n,&W);
for(int i=;i<n;i++)
scanf("%lld%lld",&w[i],&v[i]);
solve();
}
return ;
}
如果是重量不大于 W ,那么就要折半枚举+二分查找。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long LL;
const int INF=0x4fffffff;
const int EXP=1e-;
const int MS=; int n;
LL W;
LL w[MS],v[MS];
struct node
{
LL w,v;
bool operator <(const node &a) const //注意一定要加上const
{
return w<a.w||(w==a.w&&v<a.v);
}
}nodes[<<(MS/)]; LL find(LL w,int cnt)
{
int l=,r=cnt;
while(r-l>) // 左闭右开区间处理起来更方便。
{
int mid=(l+r)/;
if(nodes[mid].w<=w)
l=mid;
else
r=mid;
}
return nodes[l].v;
} void solve()
{
int n1=n/;
int cnt=;
for(int i=;i<(<<n1);i++)
{
LL sw=,sv=;
for(int j=;j<n1;j++)
{
if((i>>j)&)
{
sw+=w[j];
sv+=v[j];
}
}
nodes[cnt].w=sw;
nodes[cnt++].v=sv;
}
sort(nodes,nodes+cnt);
int last=;
for(int i=;i<cnt;i++)
{
if(nodes[last].v<nodes[i].v)
{
nodes[++last]=nodes[i];
}
}
cnt=last+;
LL ans=;
for(int i=;i< <<(n-n1);i++)
{
LL sw=,sv=;
for(int j=;j<(n-n1);j++)
{
if((i>>j)&)
{
sw+=w[n1+j];
sv+=v[n1+j];
}
}
if(sw<=W)
{
LL tv=find(W-sw,cnt);
ans=max(ans,sv+tv);
}
}
printf("%lld\n",ans);
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%lld",&n,&W);
for(int i=;i<n;i++)
scanf("%lld%lld",&w[i],&v[i]);
solve();
}
return ;
}
CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。的更多相关文章
- (容量超大)or(容量及价值)超大背包问题 ( 折半枚举 || 改变 dp 意义 )
题意 : 以下两个问题的物品都只能取有且只有一次 ① 给你 N 个物品,所有物品的价值总和不会超过 5000, 单个物品的价格就可达 10^10 ,背包容量为 B ② 给你 N (N ≤ 40 ) 个 ...
- poj3977(折半枚举+二分查找)
题目链接:https://vjudge.net/problem/POJ-3977 题意:给一个大小<=35的集合,找一个非空子集合,使得子集合元素和的绝对值最小,如果有多个这样的集合,找元素个数 ...
- Subset---poj3977(折半枚举+二分查找)
题目链接:http://poj.org/problem?id=3977 给你n个数,找到一个子集,使得这个子集的和的绝对值是最小的,如果有多种情况,输出子集个数最少的: n<=35,|a[i]| ...
- Subset POJ - 3977(折半枚举+二分查找)
题目描述 Given a list of N integers with absolute values no larger than 10 15, find a non empty subset o ...
- 中南林业大学校赛 I 背包问题 ( 折半枚举 || 01背包递归写法 )
题目链接 题意 : 中文题 分析 : 价值和重量都太过于大,所以采用折半枚举的方法,详细可以看挑战的超大背包问题 由于 n <= 30 那么可以不必直接记录状态来优化,面对每个用例 直接采用递 ...
- POJ 3977 Subset(折半枚举+二分)
SubsetTime Limit: 30000MS Memory Limit: 65536KTotal Submissions: 6754 Accepted: 1277 D ...
- POJ 2549 Sumsets(折半枚举+二分)
Sumsets Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11946 Accepted: 3299 Descript ...
- Codeforces H. Prime Gift(折半枚举二分)
题目描述: Prime Gift time limit per test 3.5 seconds memory limit per test 256 megabytes input standard ...
- POJ 2785 4 Values whose Sum is 0(折半枚举+二分)
4 Values whose Sum is 0 Time Limit: 15000MS Memory Limit: 228000K Total Submissions: 25675 Accep ...
随机推荐
- lambda表达式和ef的语句转化
这两者转化可以用linqpad进行转化, 首先推荐一个网站可以了解一下orderby的排序方式 http://www.csharpwin.com/csharpspace/614.shtml 然后下面有 ...
- CCF 201312-2 ISBN号码 (水题)
问题描述 每一本正式出版的图书都有一个ISBN号码与 之对应,ISBN码包括9位数字.1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”是分隔符(键盘上的减号),最后 ...
- c++中指针类型在c#中怎么对应?
int[] a=new int[5]; //取a[3]的地址 IntPtr addr=System.Runtime.InteropServices.Marshal.UnsafeAddrOfPinned ...
- IIS7下.NET4.0 网站UrlRewriter.dll重写无后缀路径 失效
解决方法: 1.添加通配符脚本映射,选择:C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll 2.找到和网站相对的连接池,选择 ...
- OC:习题来自平时搜索
== 第一部分 == 类变量的@protected ,@private,@public,@package,声明各有什么含义?写一个标准宏MIN,这个宏输入两个参数并返回较小的一个?面向对象的三大特征 ...
- jQuery each,避免使用js for循环
What is the difference between $.each(selector) and $(selector).each(): http://stackoverflow.com/que ...
- VPS之openVPN的安装配置
原文地址:http://www.blogjava.net/dongbule/archive/2010/11/01/336714.html 上次写的<VPS的购买和使用>中提到了openVP ...
- python三大神器之一fabric使用
fabric 是一个python包 是一个基于ssh的部署工具包 通常用来对网站 微服务等等的批量部署 例如 我有5台线上服务器 可以通过一台对着5台分发,实现自动部署的目的. 简单介绍下 fabri ...
- 自定义一个可以使用foreach语句进行迭代的类(IEnumerable)
在c#中,凡是实现了IEnumerable接口的数据类型都可以用foreach语句进行迭代访问.所以,我们要定义一个可以使用foreach进行迭代访问的类,就必须要实现IEnumerable接口. / ...
- iframe式ajax调用示例
1.新建 a.html <!doctype html> <html> <head> <meta charset='utf-8'> <title&g ...