HDU - 1085 Holding Bin-Laden Captive!(母函数)

We all know that Bin-Laden is a notorious terrorist, and he has disappeared for a long time. But recently, it is reported that he hides in Hang Zhou of China!
“Oh, God! How terrible! ”
Don’t be so afraid, guys. Although he hides in a cave of Hang Zhou, he dares not to go out. Laden is so bored recent years that he fling himself into some math problems, and he said that if anyone can solve his problem, he will give himself up!
Ha-ha! Obviously, Laden is too proud of his intelligence! But, what is his problem?
“Given some Chinese Coins (硬币) (three kinds– 1, 2, 5), and their number is num_1, num_2 and num_5 respectively, please output the minimum value that you cannot pay with given coins.”
You, super ACMer, should solve the problem easily, and don’t forget to take $25000000 from Bush!
Input
Input contains multiple test cases. Each test case contains 3 positive integers num_1, num_2 and num_5 (0<=num_i<=1000). A test case containing 0 0 0 terminates the input and this test case is not to be processed.
Output
Output the minimum positive value that one cannot pay with given coins, one line for one case.
Sample Input
1 1 3
0 0 0
Sample Output
4

题意:告诉你一元的硬币有几个,两元的硬币有几个,五元的硬币有几个,问你最小的不能由它们所组成的价值是多少。

思路:母函数模板题,输入的三个数相当于就是三个因子的终止系数,然后对答案数组从小到大扫一遍,输出第一个为0的数就行了。
母函数模板:http://blog.csdn.net/kele52he/article/details/77834848

普通母函数模板
用时300ms

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#include <set>
#include <functional>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 1e9 + 5;
const int MAXN = 8005;
const int MOD = 30021;
const double eps = 1e-8;
const double PI = acos(-1.0);

int Num;//因子个数
int n1[MAXN];//n1[i]表示该乘积表达式第i个因子的起始系数
int n2[MAXN];//n2[i]表示该乘积表达式第i个因子的终止系数
int v[MAXN];//v[i]表示该乘积表达式第i个因子的权重
int P;//P是可能的最大指数
int a[MAXN], b[MAXN];//a为计算结果,b为中间结果。 

void solve()
{
    memset(a, 0, sizeof(a));
    a[0] = 1;
    for (int i = 1; i <= Num; i++)//循环每个因子  
    {
        memset(b, 0, sizeof(b));
        for (int j = n1[i]; j <= n2[i] && j*v[i] <= P; j++)//循环每个因子的每一项  
            for (int k = 0; k + j*v[i] <= P; k++)//循环a的每个项  
                b[k + j*v[i]] += a[k];//把结果加到对应位  
        memcpy(a, b, sizeof(b));//b赋值给a  
    }
}

int main()
{
    Num = 3;
    P = 8000;
    n1[1] = 0;
    n1[2] = 0;
    n1[3] = 0;
    v[1] = 1;
    v[2] = 2;
    v[3] = 5;
    while (scanf("%d%d%d",&n2[1],&n2[2],&n2[3])!=EOF)
    {
        if (n2[1] == 0 && n2[2] == 0 && n2[3] == 0)
            break;
        solve();
        for (int i = 1; i <= 8004; i++)
            if (a[i] == 0)
            {
                printf("%d\n", i);
                break;
            }
    }
}

优化母函数模板
用时30ms

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#include <set>
#include <functional>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 1e9 + 5;
const int MAXN = 8005;
const int MOD = 30021;
const double eps = 1e-8;
const double PI = acos(-1.0);

int Num;//因子个数
int n1[MAXN];//n1[i]表示该乘积表达式第i个因子的起始系数
int n2[MAXN];//n2[i]表示该乘积表达式第i个因子的终止系数
int v[MAXN];//v[i]表示该乘积表达式第i个因子的权重
int P;//P是可能的最大指数
int a[MAXN], b[MAXN];//a为计算结果,b为中间结果。
int last;

void solve2()
{
    //初始化a,因为有last,所以这里无需初始化其他位  
    a[0] = 1;
    last = 0;
    for (int i = 1; i<=Num; i++)
    {
        int last2 = min(last + n2[i] * v[i], P);//计算下一次的last  
        memset(b, 0, sizeof(int)*(last2 + 1));//只清空b[0..last2]  
        for (int j = n1[i]; j <= n2[i] && j*v[i] <= last2; j++)//这里是last2  
            for (int k = 0; k <= last&&k + j*v[i] <= last2; k++)//这里一个是last,一个是last2  
                b[k + j*v[i]] += a[k];
        memcpy(a, b, sizeof(int)*(last2 + 1));//b赋值给a,只赋值0..last2  
        last = last2;//更新last  
    }
}

int main()
{
    int i;
    Num = 3;
    P = 8000;
    n1[1] = 0;
    n1[2] = 0;
    n1[3] = 0;
    v[1] = 1;
    v[2] = 2;
    v[3] = 5;
    while (scanf("%d%d%d",&n2[1],&n2[2],&n2[3])!=EOF)
    {
        if (n2[1] == 0 && n2[2] == 0 && n2[3] == 0)
            break;
        solve2();
        for ( i = 1; i <= last; i++)
            if (a[i] == 0)
                break;
        printf("%d\n", i);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值