Problem U
2016-05-29 22:43
267 查看
简单题意
有分别价值为1,2,3,4,5,6的6种物品,每种价值物品有相对应的数量,问能否将物品分成两份,使得两份总价值相等。
解题思路形成过程
老师上课讲的例题,主要思想就是把一个多重背包问题,转化为01背包或完全背包来解决。用三个数组:c是费用,w是价值,m是数量,如果物品足够塞满背包转化为完全背包问题,否则转化为01背包问题。
感想
学会了一个套路,将多重背包问题,转换为01背包或完全背包的问题
AC代码
#include<iostream>
#include<stdio.h>
#include<fstream>
using namespace std;
const int INF=100000000;
int f[240005];//f[j]相当于f[i][j]: 考虑1...i个物品,恰好放到容量为j,所能达到的最大价值
int v; //背包容量
//处理一个完全背包(该种物品不限量)
void complete_pack(int *a,int c,int w)
{
for(int i=c;i<=v;i++)
a[i]=max(a[i],a[i-c]+w);
}
//处理一个 01背包 (该种物品只有一个)
void zeroone_pack(int *a,int c,int w)
{
for(int i=v;i>=c;i--)
a[i]=max(a[i],a[i-c]+w);
}
//处理一个多重背包 (该种物品指定上限)
void mutiple_pack(int *a,int c,int w,int m)
{
//该种物品足以塞满背包-->转化为完全背包
if(c*m>=v){
complete_pack(a,c,w);
return;
}
int k=1;
while(k<m)
{
zeroone_pack(a,k*c,k*w);
m=m-k;
k=2*k;
}
zeroone_pack(a,c*m,w*m);
}
int main(){
ifstream cin("in.txt");
freopen("in.txt","r",stdin);
int sum,c[7],w[7],m[7],cas=0;
while(cin>>m[1]>>m[2]>>m[3]>>m[4]>>m[5]>>m[6]&&(m[1]||m[2]||m[3]||m[4]||m[5]||m[6])){
sum=0;
for(int i=1;i<=6;i++){
c[i]=w[i]=i;
sum+=c[i]*m[i];
}
printf("Collection #%d:\n",++cas);
if(sum&1){
puts("Can't be divided.\n");
}else{
sum/=2;
v=sum;
for(int i=1;i<=sum;i++)
f[i]=-INF;
f[0]=0;
for(int i=1;i<=6;i++)
mutiple_pack(f,c[i],w[i],m[i]);//c是费用,w是价值,m是数量
if(f[v]<0){
puts("Can't be divided.\n");
}else{
puts("Can be divided.\n");
}
}
}
return 0;
}
有分别价值为1,2,3,4,5,6的6种物品,每种价值物品有相对应的数量,问能否将物品分成两份,使得两份总价值相等。
解题思路形成过程
老师上课讲的例题,主要思想就是把一个多重背包问题,转化为01背包或完全背包来解决。用三个数组:c是费用,w是价值,m是数量,如果物品足够塞满背包转化为完全背包问题,否则转化为01背包问题。
感想
学会了一个套路,将多重背包问题,转换为01背包或完全背包的问题
AC代码
#include<iostream>
#include<stdio.h>
#include<fstream>
using namespace std;
const int INF=100000000;
int f[240005];//f[j]相当于f[i][j]: 考虑1...i个物品,恰好放到容量为j,所能达到的最大价值
int v; //背包容量
//处理一个完全背包(该种物品不限量)
void complete_pack(int *a,int c,int w)
{
for(int i=c;i<=v;i++)
a[i]=max(a[i],a[i-c]+w);
}
//处理一个 01背包 (该种物品只有一个)
void zeroone_pack(int *a,int c,int w)
{
for(int i=v;i>=c;i--)
a[i]=max(a[i],a[i-c]+w);
}
//处理一个多重背包 (该种物品指定上限)
void mutiple_pack(int *a,int c,int w,int m)
{
//该种物品足以塞满背包-->转化为完全背包
if(c*m>=v){
complete_pack(a,c,w);
return;
}
int k=1;
while(k<m)
{
zeroone_pack(a,k*c,k*w);
m=m-k;
k=2*k;
}
zeroone_pack(a,c*m,w*m);
}
int main(){
ifstream cin("in.txt");
freopen("in.txt","r",stdin);
int sum,c[7],w[7],m[7],cas=0;
while(cin>>m[1]>>m[2]>>m[3]>>m[4]>>m[5]>>m[6]&&(m[1]||m[2]||m[3]||m[4]||m[5]||m[6])){
sum=0;
for(int i=1;i<=6;i++){
c[i]=w[i]=i;
sum+=c[i]*m[i];
}
printf("Collection #%d:\n",++cas);
if(sum&1){
puts("Can't be divided.\n");
}else{
sum/=2;
v=sum;
for(int i=1;i<=sum;i++)
f[i]=-INF;
f[0]=0;
for(int i=1;i<=6;i++)
mutiple_pack(f,c[i],w[i],m[i]);//c是费用,w是价值,m是数量
if(f[v]<0){
puts("Can't be divided.\n");
}else{
puts("Can be divided.\n");
}
}
}
return 0;
}
相关文章推荐
- 详解Android应用中屏幕尺寸的获取及dp和px值的转换
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android dpi,dip,dp的概念以及屏幕适配
- Android px、dp、sp之间相互转换
- HP data protector软件学习1--基本角色与基本工作流程
- HP data protector软件学习2--软件组成与界面介绍
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告
- soj1005. Roll Playing Games
- 01背包问题