1. 程式人生 > >HDU 1171 Big Event in HDU(母函數或01背包)

HDU 1171 Big Event in HDU(母函數或01背包)

less diff pos span ren 初始化 nes careful ont

Big Event in HDU

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


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

Author lcy

Recommend We have carefully selected several similar problems for you: 2602 1203 2159 2955 2844 分析:要將所有的值分成兩個相近的部分,那麽總值一定能得到,如果我們能找到一個最接近它的二分之一的值能得到,那麽另一部分也一定能得到 母函數解法 ,表示不懂為什麽最後不能直接判if(a[i]>0) 而是if(a[i]) 代碼如下:
#include<iostream>
#include <cstring>
using namespace std;
const int  M=50*50*100+10;   //M為(x的最大指數+1)
#define MAXN 52      //MAXN為最大有多少項相乘
typedef long long ll;
ll a[M],b[M];//a[M]中存最終項系數;b[M]中存取中間變量;
struct node
{
    int val;
    int num;
}c[MAXN];
int main()
{
    int m,n;
    int i,j,k,sum;
    while(scanf("%d",&n)!=EOF&&n>=0)
    {
        sum=0;
        memset(a,0,sizeof(a));
        m=n;
        for(int i=0;i<n;i++)
        {
          scanf("%d%d",&c[i].val,&c[i].num);
          sum+=c[i].val*c[i].num;
        }
        //可以加一個跳出循環的條件
        //n為所求的指數的值: ";
        //因為只求指數為n的系數的值:所以循環只到n就結束
        for(i=0;i<=c[0].val*c[0].num;i+=c[0].val)//初始化第一個式子:(1+X^2+X^3+...) 所以將其系數分別存到a[n]
        {
            a[i]=1;
            b[i]=0;
        }
        for(i=2;i<=m;i++)//從第2項式子一直到第n項式子與原來累乘項的和繼續相乘
        {
            for(j=0;j<=sum;j++)//從所累乘得到的式子中指數為0遍歷到指數為n 分別與第i個多項式的每一項相乘
                 for(k=0;k+j<=sum&&k<=c[i-1].val*c[i-1].num;k+=c[i-1].val)//第i個多項式的指數從0開始,後面的每項指數依次比前面的多i,比如當i=3時,第3項的表達式為(1+x^3+x^6+x^9+……),直到所得指數的值i+j>=n退出
                 {
                     b[j+k]+=a[j];//比如前面指數為1,系數為3,即a[1]=3 的一項和下一個表達式的指數為k=3的相乘,則得到的式子的系數為,b[j+k]=b[4]+=a[1],又a[1]=3,所以指數為4的系數為b[4]=3;
                 }
             for(j=0;j<=sum;j++)//  然後將中間變量b數組中的值依次賦給數組a,然後將數組b清零,繼續接收乘以下一個表達式所得的值
              {
                  a[j]=b[j];
                  b[j]=0;
              }
        }
        for(int i=sum/2;i>=0;i--)
        {
          if(a[i])
          {
              printf("%d %d\n",sum-i,i);
              break;
          }
        }
    }

    return 0;
}

  01背包:

#include <cstdio>
#include <iostream>
#include  <algorithm>
#include <vector>
#include <cstring>
using namespace std;
const int MAXN=50*50*100+10;
#define INF 0x3f3f3f3f
vector<int>V;
int dp[MAXN];
int n;
int main()
{
      int t,n,v,m,sum;
       while(scanf("%d",&n)!=EOF&&n>=0){
           sum=0;
           V.clear();
           while(n--){
           scanf("%d%d",&v,&m);
           sum+=v*m;
            for(int i=0;i<m;i++)
            V.push_back(v);
           }
           fill(dp,dp+sum+1,INF);
           dp[0]=0;
           for(int i=0;i<V.size();i++)
              for(int j=sum;j>=V[i];j--)
              {
                 dp[j]=min(dp[j],dp[j-V[i]]+V[i]);
              }
           for(int i=sum/2;i>=0;i--)
           {
              if(dp[i]<=100000000)
              {
                printf("%d %d\n",sum-i,i);
                break;
              }
           }
       }
    return 0;
}

HDU 1171 Big Event in HDU(母函數或01背包)