博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
题解 P1537 【弹珠】
阅读量:6192 次
发布时间:2019-06-21

本文共 1426 字,大约阅读时间需要 4 分钟。

朴素的多重背包

本蒟蒻的第一篇题解

勿喷

虽然有大佬已经提到过该做法,但没有代码,本蒟蒻在此补充

PS:大佬请略过本题解,建议dp初学者看

正文:

首先要了解多重背包的含义:“给定N种物品,其中第i种物品的体积为Vi,价值为Wi,并且有Ci个。有一个容量为M的背包,要求选择若干个物品放入背包,使得物品总体积不超过M的前提下,物品总价值最大。” ——《算法竞赛》 李煜东

对应本题,给出了6种价值的石头,每种石头“体积”与“价值”

都为i(1<=i<=6),可以选a[i]个;而题目中的要求是是否 存在

某种分配方式,使得背包的总价值为s/2(s为所有石头的价值

总和)。

因此对递推式进行一点小改动,

将f[i][j]=min(f[i-1][j-i*k],f[i][j])中的min改成sum即可(代码中会提到这一段)。

(另外,f[i][j]的含义:在选择1~i种物品、总价值为j的情况下的方案数)

因此,我们的思路就很清晰了:

1.确定状态转移方程:f[i][j]=min(f[i-1][j-i*k];

2.确定边界:f[i][i*j]=1(j<=a[i]);

3.求解:f[i][s/2]是否非0(1<=i<=6)

上代码:

#include
using namespace std; int a[7],s=0,x,j,mark; long long f[7][60010];//这里的f用longlong存储,可以统计每种价值的表示方式数。当然本题不需要,用bool来存储是 //否可表就可以了 inline int rd(){ //读优 int ans=0,flag=1; char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')flag=-1,ch=getchar(); while(ch>='0'&&ch<='9'){ ans=ans*10+ch-48; return ans*flag; } int main(){ for(register int i=1;i<=6;i++){ //读入第一组数据 a[i]=rd(); s+=a[i]*i; } int i1=0; while(s!=0){ //当s等于0时,输入结束 i1++;//i1记录第几组数据 mark=0,memset(f,0,sizeof(f));//初始化 cout<<"Collection #"<
<<':'<
i*k) f[i][j]+=f[i-1][j-i*k];//转移方程 } } for(register int i=1;i<=6;i++){ if(f[i][s]){ //存在一种表示s的方式 mark=1; printf("Can be divided.\n\n"); break; } } if(mark==0){ printf("Can't be divided.\n\n"); } } s=0; for(register int i=1;i<=6;i++){ a[i]=rd(); s+=a[i]*i; }//读入下一组数据 } return 0; }

转载于:https://www.cnblogs.com/Zenyz/p/9794599.html

你可能感兴趣的文章
RTP协议分析
查看>>
前后端分离了,然后呢?(转)
查看>>
自定义控件:滑动开关按钮
查看>>
js修改后没反应-看看是不是取的缓存
查看>>
【iCore3 双核心板_ uC/OS-III】例程十一:任务消息队列
查看>>
C#的delegate简单练习
查看>>
【301】IDL与C#混合编程
查看>>
分治法应用之一——Strassen矩阵乘法(转)
查看>>
linux-diff命令
查看>>
必须关注的25位知名JavaScript开发者
查看>>
linq直接执行sql语句
查看>>
POJ - 1170 Shopping Offers (五维DP)
查看>>
【Linux学习】Linux的文件权限(一)
查看>>
python的内存管理机制
查看>>
一个基于 EasyUI 的前台架构(3)封装操作Tabs的JS代码
查看>>
《深入理解Android 卷III》第四章 深入理解WindowManagerService
查看>>
hdu 5093 二分匹配
查看>>
a erlang crawler
查看>>
hdu 3586 Information Disturbing(树形dp + 二分)
查看>>
无聊,只发两张图……
查看>>