Problem Description
Nowadays, we all know that Computer College is the biggest department in HDU. But, maybe you don't know that Computer College had ever been split into Computer College and Software College in 2002.
The splitting is absolutely a big event in HDU! At the same time, it is a trouble thing too. All facilities must go halves. First, all facilities are assessed, and two facilities are thought to be same if they have the same value. It is assumed that there is N (0<N<1000) kinds of facilities (different value, different kinds).
 
Input
Input contains multiple test cases. Each test case starts with a number N (0 < N <= 50 -- the total number of different facilities). The next N lines contain an integer V (0<V<=50 --value of facility) and an integer M (0<M<=100 --corresponding number of the facilities) each. You can assume that all V are different.
A test case starting with a negative integer terminates input and this test case is not to be processed.
 
Output
For each case, print one line containing two integers A and B which denote the value of Computer College and Software College will get respectively. A and B should be as equal as possible. At the same time, you should guarantee that A is not less than B.
 

Sample Input

2
10 1
20 1
3
10 1
20 2
30 1
-1
 
Sample Output
20 10
40 40
 
题意:大概就是给你一堆东西,第一行数据表示东西的种类,而后面再输入两个数,第一个代表物品的价值(v) ,第二个代表物品的个数(n),然后需要你开始按照价值分配给 a 和 b 两个组,同时要求 a ,b 两组后面的价值要尽可能的接近,并且保证 a 组的所获得价值不小于 b 组所获得的价值。
 
解题思路
刚拿到这题的时候觉得应该是背包的一种,首先 01背包是每种物品只能取一次,完全背包每种物品能取无限多次数。而这题可以把看作01背包来求解,就是每个价值相同的多件物品可以拆分成一件一件的看作不同的物品,就是数据有点大可能会超时。
所以先尝试一下,结果a了
附上ac代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int v[]={};
int f[]={};
int main()
{
int t;
while(cin>>t&&t>)
{
int sum=;
int count=;
memset(v,,sizeof(v));
memset(f,,sizeof(f));
while(t--)
{
int n,m;
cin>>n>>m;
for(int i=;i<m;i++)
{
v[count++]=n;
sum+=n;
}
}
for(int i=;i<count;i++)
{
for(int j=sum/;j>=v[i];j--)
{
f[j]=max(f[j],f[j-v[i]]+v[i]);
}
}
cout<<sum-f[sum/]<<" "<< f[sum/]<<endl;
}
return ;
}

后面上网查了一下,发现了一个什么新概念,母函数的方法用来处理这种有一个或者多个的题目,具体的什么也没怎么看懂,感觉挺复杂的样子,但是这种题相当于一种模板题目,从大佬博客里面抄来的模板。

//为计算结果,b为中间结果。
int a[MAX],b[MAX];
//初始化a
memset(a,,sizeof(a));
a[]=;
for (int i=;i<=;i++)//循环每个因子
{
memset(b,,sizeof(b));
for (int j=n1[i];j<=n2[i]&&j*v[i]<=P;j++)//循环每个因子的每一项
for (int k=;k+j*v[i]<=P;k++)//循环a的每个项
b[k+j*v[i]]+=a[k];//把结果加到对应位
memcpy(a,b,sizeof(b));//b赋值给a
}

P是可能的最大指数。拿钞票组合这题来说,如果要求15元有多少组合,那么P就是15;如果问最小的不能拼出的数值,那么P就是所有钱加起来的和。P有时可以直接省略。

如果n2是无穷,那么第二层循环条件j<=n2[i]可以去掉。

还有一种提高效率的模板2:

用一个last变量记录目前最大的指数,这样只需要在0..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
}

而套用模板二ac的本题代码

#include <iostream>
#include <cstring>
using namespace std;
#define MAX 250010
int n,a[MAX],b[MAX],i,j,k,last,last2,v[],m[];
int main()
{
while ((cin>>n)&&n>=)
{
for (i=;i<n;i++)
cin>>v[i]>>m[i];
a[]=;
last=;
for (i=;i<n;i++)
{
last2=last+m[i]*v[i];
memset(b,,sizeof(int)*(last2+));
for (j=;j<=m[i];j++)
for (k=;k<=last;k++)
b[k+j*v[i]]+=a[k];
memcpy(a,b,sizeof(int)*(last2+));
last=last2;
}
for (i=last/;i>=&&a[i]==;i--);
cout<<last-i<<' '<<i<<endl;
}
return ;
}

hdu 1171 (背包或者母函数问题)的更多相关文章

  1. hdu 1171 Big Event in HDU (01背包, 母函数)

    Big Event in HDU Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  2. HDU 1171 背包

    Big Event in HDU Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  3. hdu 1171 Big Event in HDU(母函数)

    链接:hdu 1171 题意:这题能够理解为n种物品,每种物品的价值和数量已知,现要将总物品分为A,B两部分, 使得A,B的价值尽可能相等,且A>=B,求A,B的价值分别为多少 分析:这题能够用 ...

  4. HDU 1171 Big Event in HDU(01背包)

    题目地址:HDU 1171 还是水题. . 普通的01背包.注意数组要开大点啊. ... 代码例如以下: #include <iostream> #include <cstdio&g ...

  5. Big Event in HDU(HDU1171)可用背包和母函数求解

    Big Event in HDU  HDU1171 就是求一个简单的背包: 题意:就是给出一系列数,求把他们尽可能分成均匀的两堆 如:2 10 1 20 1     结果是:20 10.才最均匀! 三 ...

  6. 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 ...

  7. hdu 01背包汇总(1171+2546+1864+2955。。。

    1171 题意比较简单,这道题比较特别的地方是01背包中,每个物体有一个价值有一个重量,比较价值最大,重量受限,这道题是价值受限情况下最大,也就值把01背包中的重量也改成价值. //Problem : ...

  8. 1171 Big Event in HDU 01背包

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1171 题意:把商品分成两半,如不能均分,尽可能的让两个数相接近.输出结果:两个数字a,b且a>=b. ...

  9. HDU 1171 01背包

    http://acm.hdu.edu.cn/showproblem.php?pid=1171 基础的01背包,求出总值sum,背包体积即为sum/2 #include<stdio.h> # ...

随机推荐

  1. error C2712: Cannot use __try in functions that require object unwinding

    转自VC错误:http://www.vcerror.com/?p=52 问题描述: error C2712: Cannot use __try in functions that require ob ...

  2. Laravel5.4中自定义404等错误页面

    1.在resources/views/下简历文件夹error,在error文件中建立"404.blade.php文件". <!DOCTYPE html PUBLIC &quo ...

  3. LightOJ-1214-Large Division-大数取余

    Given two integers, a and b, you should check whether a is divisible by b or not. We know that an in ...

  4. zookeeper 选举白话理解

  5. Spring - JUnit整合测试

    1.导包:test.jar - (依赖 aop.jar) 2.使用@RunWith注解创建spring容器 - @RunWith(SpringJUnit4ClassRunner.class) 3.使用 ...

  6. 2018-8-10-win10-uwp-打开文件管理器选择文件

    title author date CreateTime categories win10 uwp 打开文件管理器选择文件 lindexi 2018-08-10 19:16:50 +0800 2018 ...

  7. new linux setup, yum command

    7  yum list 9  cd /etc/yum.repos.d/ 55  history | grep yum 56  yum -y list screen* 57  yum -y instal ...

  8. mongodb 3.2 yaml 配置详解及范例

    mongodb3.x版本后就是要yaml语法格式的配置文件,下面是yaml配置文件格式如下:官方yaml配置文件选项参考:https://docs.mongodb.org/manual/ ... #c ...

  9. 调整element-ui中多个button处于同一行

    参考: https://element.eleme.cn/#/zh-CN/component/dropdown <el-row> <el-button-group style=&qu ...

  10. Keywords Search HDU2222 AC自动机模板题

    ac自动机说起来很复杂,其实和kmp是一样的思路,都是寻找相同前后缀,减少跳的次数.只要理解了kmp是怎么求next数组的,ac自动机bfs甚至比knp还好写. 这里大致说一下kmp求next数组的方 ...