hdu acm steps Big Event in HDU
上网搜了一下这道题的解法,主要有两个方法,一种是采用母函数的方法,一种是采用0/1背包的方法。
先说一下母函数,即生成函数,做个比喻,母函数就是一个多项式前面的系数的一个整体的集合,而子函数就是这个多项式每一项前面的系数。主要用于解决组合问题,类似于钱币的组合问题。利用母函数解题时,首先要写出表达式,通常是多项式的乘积形式,类似于:(x^(v[K]*n1[K])+x^(v[K]*(n1[K]+1))+x^(v[K]*(n1[K]+2))+...+x^(v[K]*n2[K]))。
例如,对于有n种物品,如果第i种物品有ki个,我们可以列式n个项相乘 (x^0+x^1+...x^k1)*(x^0+x^1+...x^k2)*...*(x^0+x^1+...x^kn),每一项表示对于第i件物品,可以有(x^0+x^1+...x^ki)中取法,【注意系数都为1,因为同种物品取i件,它的取法是1】多项相乘:因为取m件物品这件事实要分为对n种物品各取分别取1次【0~ki个】, 是组合计数的乘法原理, x^m 的系数是组合成m件物品的所有方案数
一、母函数解题的核心就是要找到:
k(对应具体问题中物品的种类数)、
v[i](表示该乘积表达式第i个因子的权重,对应于具体问题的每个物品的价值或者权重)、
n1[i](表示该乘积表达式第i个因子的起始系数,对应于具体问题中的每个物品的最少个数,即最少要取多少个)、
n2[i](表示该乘积表达式第i个因子的终止系数,对应于具体问题中的每个物品的最多个数,即最多要取多少个)。
之后迭代计算,并将结果放在一个数组a中。其中a[i]表示权重为i的组合数。
二、母函数对应的具体题型:
主要是普通型母函数,主要用在组合和整数拆分问题上。
关于母函数的百度百科:http://baike.baidu.com/view/2415279.htm
三、模板
先贴一下我收集到的母函数模板:
模板一
//a为计算结果,b为中间结果。
int a[MAX],b[MAX];
//初始化a
memset(a,,sizeof(a));
a[]=;
for (int i=;i<=17;i++)//循环每个因子
{
memset(b,,sizeof(b));
for (int j=n1[i];j<=n2[i]&&j*v[i]<=P;j++)//循环每个因子的每一项 ,p为可能的最大指数
for (int k=;k+j*v[i]<=P;k++)//循环a的每个项
b[k+j*v[i]]+=a[k];//把结果加到对应位
memcpy(a,b,sizeof(b));//b赋值给a
}
有一个last变量记录当前的最大指数,可以提高程序的效率:
模板二:
//初始化a,因为有last,所以这里无需初始化其他位
a[]=;
int last=;
for (int i=;i<K;i++)
{
int last2=min(last+n[i]*v[i],P);//计算下一次的last
memset(b,,sizeof(int)*(last2+));//只清空b[0..last2]
for (int j=n1[i];j<=n2[i]&&j*v[i]<=last2;j++)//这里是last2
for (int k=;k<=last&&k+j*v[i]<=last2;k++)//这里一个是last,一个是last2
b[k+j*v[i]]+=a[k];
memcpy(a,b,sizeof(int)*(last2+));//b赋值给a,只赋值0..last2
last=last2;//更新last
}
因为刚刚接触到acm,最近做的事简单的背包专题,所以此处仅附上背包的思路和解法:
思路:将背包的容量定为所有物品总价值的一半,然后就是0/1背包问题,dp[half]中存储的就是较小的半份。其中,dp[j]表示选前i间物品时,预算为j时背包中装的最大总价值。
状态转移方程为:dp[j]=max{dp[j],dp[j-f[i].v]+f[i].v};
#include"iostream"
#include"stdio.h"
#include"algorithm"
#include"string.h"
#include"cmath"
#define mx 105
using namespace std;
int dp[];//注意dp数组的大小
struct node
{
int v;
int c;
}f[mx];
bool cmp(const node a,const node b)
{
if(a.v!=b.v) return a.v<b.v;
}
int main()
{
int n,i,j,k;
while(cin>>n,n>)
{
int sum=,half;
for(i=;i<n;i++)
{
cin>>f[i].v>>f[i].c;
sum+=f[i].v*f[i].c;
}
half=sum/;
sort(f,f+n,cmp);
memset(dp,,sizeof(dp));
for(i=;i<n;i++)
{
for(k=;k<=f[i].c;k++)
{
for(j=half;j>=f[i].v;j--)
{
if(dp[j]<dp[j-f[i].v]+f[i].v) dp[j]=dp[j-f[i].v]+f[i].v;
}
}
}
cout<<sum-dp[half]<<' '<<dp[half]<<endl;
}
return ;
}
hdu acm steps Big Event in HDU的更多相关文章
- hdu ACM Steps Section 1 花式A+B 输入输出格式
acm与oi很大的一个不同就是在输入格式上.oi往往是单组数据,而acm往往是多组数据,而且题目对数据格式往往各有要求,这8道a+b(吐槽..)涉及到了大量的常用的输入输出格式.https://wen ...
- HDU 1171 Big Event in HDU 多重背包二进制优化
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1171 Big Event in HDU Time Limit: 10000/5000 MS (Jav ...
- hdu1171 Big Event in HDU 01-背包
转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1171 Problem ...
- Big Event in HDU(多重背包套用模板)
http://acm.hdu.edu.cn/showproblem.php?pid=1171 Big Event in HDU Time Limit: 10000/5000 MS (Java/Othe ...
- HDU 1171 Big Event in HDU (多重背包变形)
Big Event in HDU Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- HDU-1171 Big Event in HDU
Big Event in HDU Problem Description Nowadays, we all know that Computer College is the biggest depa ...
- hdu acm 1028 数字拆分Ignatius and the Princess III
Ignatius and the Princess III Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K ...
- Big Event in HDU
Description Nowadays, we all know that Computer College is the biggest department in HDU. But, maybe ...
- Big Event in HDU(HDU1171)可用背包和母函数求解
Big Event in HDU HDU1171 就是求一个简单的背包: 题意:就是给出一系列数,求把他们尽可能分成均匀的两堆 如:2 10 1 20 1 结果是:20 10.才最均匀! 三 ...
随机推荐
- Python操作Mysql实例代码教程在线版(查询手册)
本文介绍了Python操作MYSQL.执行SQL语句.获取结果集.遍历结果集.取得某个字段.获取表字段名.将图片插入数据库.执行事务等各种代码实例和详细介绍,代码居多,是一桌丰盛唯美的代码大餐 实 ...
- Java for LeetCode 035 Search Insert Position
Given a sorted array and a target value, return the index if the target is found. If not, return the ...
- sql,联合主键,按id分组求版本号最大值的集合
表结构如下: /* SQLyog v10.2 MySQL - 5.5.39 ************************************************************** ...
- [Android Pro] ant 编译android工程
参考文章: http://blog.csdn.net/xyz_lmn/article/details/7268582?reload http://hubingforever.blog.163.com/ ...
- 埃及分数(codevs 1288)
题目描述 Description 在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数. 如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的. 对于一 ...
- Linux配置SSH公钥认证与Jenkins远程登录进行自动发布
公钥认证,是使用一对加密字符串,一个称为公钥(public key), 任何人都可以看到其内容,用于加密:另一个称为密钥(private key),只有拥有者才能看到,用于解密. 在使用jenkins ...
- MySQL Auto_Increment属性应用
我们经常要用到唯一编号,以标识记录.在MySQL中可通过数据列的AUTO_INCREMENT属性来自动生成.MySQL支持多种数据表,每种数据表的自增属性都有差异,这里将介绍各种数据表里的数据 ...
- 如何为Linux生成和打上patch
通过diff工具生成补丁, patch工具打上补丁. 在使用diff之前, 你需要保留一份未修改过的源码, 然后在其它地方修改源码的一份拷贝. diff对比这两份源码生成patch. 修改过的源码必须 ...
- 蓝桥杯 入门训练 Fibonacci数列(水题,斐波那契数列)
入门训练 Fibonacci数列 时间限制:1.0s 内存限制:256.0MB 问题描述 Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1. 当n比较大时,Fn也非 ...
- laravel数据库查询是use方法的使用
){ return $query->where('effectivetime','<',date('Y-m-d')); }else{ ...