POJ1014
今天硬着头皮看了一下母函数。发现还是懂了一点点呢。
于是果断找了一个母函数的水题给刷了一下。A了呢。
首先强势声明,这个题目绝对是个水题。
题目编号:poj1014
题目描述如下:
Description
Marsha and Bill own a collection of marbles. They want to split the collection among themselves so that both receive an equal share of the marbles. This would be easy if all the marbles had the same value, because then they could just split the collection in half. But unfortunately, some of the marbles are larger, or more beautiful than others. So, Marsha and Bill start by assigning a value, a natural number between one and six, to each marble. Now they want to divide the marbles so that each of them gets the same total value. Unfortunately, they realize that it might be impossible to divide the marbles in this way (even if the total value of all marbles is even). For example, if there are one marble of value 1, one of value 3 and two of value 4, then they cannot be split into sets of equal value. So, they ask you to write a program that checks whether there is a fair partition of the marbles.
Input
Each line in the input file describes one collection of marbles to be divided. The lines contain six non-negative integers n1 , . . . , n6 , where ni is the number of marbles of value i. So, the example from above would be described by the input-line "1 0 1 2 0 0". The maximum total number of marbles will be 20000.
The last line of the input file will be "0 0 0 0 0 0"; do not process this line.
The last line of the input file will be "0 0 0 0 0 0"; do not process this line.
Output
For each collection, output "Collection #k:", where k is the number of the test case, and then either "Can be divided." or "Can't be divided.".
Output a blank line after each test case.
Output a blank line after each test case.
Sample Input
1 0 1 2 0 0 1 0 0 0 1 1 0 0 0 0 0 0
Sample Output
Collection #1: Can't be divided. Collection #2: Can be divided.
首先这个题目的意思是给你价值为1-6的价值的物品的个数。求能否把所有的物品分为两半使得两边的价值相等。
看完题目大家肯定就知道这是一个背包的题目了,同时如果有必要剪枝的话,深度搜索也是完全没压力的。
这不是我今天想说的重点,我想说的是用母函数的方法来做这个题目。
讲到母函数,大家就用明白母函数的定义。
母函数可以用如下的定义表示:
F(x)=a[0]+a[1]*x+a[2]*x^2+a[3]*x^3+……+a[n]*x^n;
这里n是我们要求的最高的级数。
对于函数中间的每一个单项式,指数表示取得的总价值,前面的系数表示取得该价值可选的种类数。
这样取第i中物品(即单个价值为i的物品)就是在原来的多项式上乘以一个(1+x^i+x^2i+x^3i+……+X^ki)k表示第i种物品的个数。
这样求出所有物品的价值总和sum,看看最终的多项式里面x^(sum/2)的系数。(如果sum为奇数显然不可分,可在读数的时候就判断哦)
如果该系数为0,则不能平分,反之可以平分。
同时,做这个题目无论用深搜,背包,或者母函数做,都有一个剪枝是必须的。
那就是题目输入的物品的个数可能很大。
但是是不是物品数越多越难分呢?
显然不是,如果输入的物品的个数是一个大于6的奇数,那么它和5个物品产生的影响是一样的;如果是一个大于6的偶数,那么它和6个该物品产生的影响是一样的(仔细想想为什么,这是题目的关键)。
但这里题目基本上就没什么问题了。
上代码:
#include <iostream> #include <cstdio> #include <cstring> #define maxn 200 using namespace std; int c1[maxn],c2[maxn],sum,a[7]; bool getnum() { for (int i=1; i<=6; i++) scanf("%d",&a[i]); for (int i=1; i<=6; i++) if (a[i]>6) { if (a[i]&1) a[i]=5; else a[i]=6; } sum=0; for (int i=1; i<=6; i++) sum+=i*a[i]; return sum>0; } bool place() { sum>>=1; memset(c1,0,sizeof c1);memset(c2,0,sizeof c2); for (int i=1; i<=min(sum,a[1]); i++) c1[i]=i; c1[0]=1; for (int i=2; i<=6; i++) { //for (int j=0; j<=sum; j++) cout<<c1[j]<<' '; cout<<endl; if (c1[sum]) return true; memset(c2,0,sizeof c2); for (int j=0; j<=sum; j++) c2[j]=c1[j]; for (int j=0; j<=sum; j++) { for (int k=1; k<=a[i]; k++) if (j+k*i<=sum) c2[j+k*i]+=c1[j]; else break; } swap(c1,c2);//这句在C++中编译是错的,只有在G++中才有用,但是直接交换地址应该是快很多的哦。 } return c1[sum]>0; } int main() { int cas=0; while (getnum()) { if (cas) printf("\n"); if (sum&1) { printf("Collection #%d:\nCan't be divided.\n",++cas); continue; } if (place()) printf("Collection #%d:\nCan be divided.\n",++cas); else printf("Collection #%d:\nCan't be divided.\n",++cas); } return 0; }
| POJ 1014 | Accepted | 688 KB | 0 ms | G++ | 1364 B | 2013-09-10 16:59:50 |
如有转载,请注明出处(http://www.cnblogs.com/lochan)
浙公网安备 33010602011771号