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);
    }

}
發佈了93 篇原創文章 · 獲贊 78 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章