1. 程式人生 > >HDU 1171 Big Event in HDU(母函式||DP)

HDU 1171 Big Event in HDU(母函式||DP)

Big Event in HDU

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 22991    Accepted Submission(s): 8079


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  WA了 好多次  就以為結束條件寫的 while(cin >> n && n!=-1)   它要是提示時間超限也行呀。。
無語。。不吐了,進入正題
題意: 杭電本來只有一個計算機院,但是要分出來一個軟體院 
 就相當與兄弟兩個要分家了,家產也應該分了。
輸入 n
n行裝置, 第一個數是價值,第一個數是數量。
輸出:一行,計算機院和軟體院最終所得價值。(能平分是最好,前提裝置不能被破壞)不能正好平分就儘可能的保證公平,計算機院的要多一些
思路:
用母函式模板進行一些變形
AC程式碼
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#define MAXN 1001000
using namespace std;

int value[200],number[200],ans[MAXN],temp[MAXN];
int main()
{
    int n,i,j,k;
    while(cin >> n&&n>=0)
    {
        int max = 0;
        for(i=0; i<n; i++)
        {
            cin >> value[i] >> number[i];
            max += value[i] * number[i]; //裝置的總價值
        }
        int mid = max/2 ;   //情況最好的時候是平分 即mid
        memset(ans,0,sizeof(int)*mid+10);
        memset(temp,0,sizeof(int)*mid+10);
        for(i=0; i<=number[0]; i++)     //用母函式數法 把第一排賦初值
            ans[i*value[0]] = 1;
        for(i=1; i<n; i++)    //還需要迴圈 n—1次
        {
            for(j=0; j<=mid; j++)
                for(k=0; (k*value[i]+j)<=mid&&k<=number[i]; k++)  //k是第二排的數量,數量要小於題目所給的數量,所以k小於number[i],
                {
                    temp[j+k*value[i]] +=ans[j];
                }
            for(j=0; j<=mid; j++)
            {
                ans[j] = temp[j];
                temp[j] = 0;
            }
        }
       /* ************************************************ */
       /*    以上就是把所有的mid一下的情況都求了出來       */
       /*    下面就開始找,這種情況有沒有存在,如果輸出    */
       /* ************************************************ */
        for(i=mid; i>=0; i--)
            if(ans[i]!=0)
                break;
        cout << max - i<<" "<< i << endl;
    }
    return 0;
}