Big Event in HDU

来源:互联网 发布:java抽象类的特点 编辑:程序博客网 时间:2024/05/22 13:44

Big Event in HDU

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


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
210 120 1310 1 20 230 1-1
 

Sample Output
20 1040 40
 

很有研究的一道题目
由于c[i]存放的是构成i的方法数目,因此求平均值只需要看c[sum/2]是否不等于0
再仔细考虑,sum为偶数,则平均数一定是整数,只需要看c[sum/2]?=0
sum为奇数,则一定不能平均,只需要从前面或者后面,找下一个c[i]不为0的i值,即为相对平均的数字

#include<stdio.h>
#include<string.h>
struct E {
    int value,num;
}buf[51];
//50*100*50=250000
int c1[250001],c2[250001];
int main(){
  //  freopen("in.txt","r",stdin);
    int zu;
    while(scanf("%d",&zu)!=EOF ){
        //注意这里组是整数,不能判zu!=-1,这样会tle
        if(zu<0){
            break;
        }
        //清空操作
        /*for(int i=0;i<50;i++){
            buf[i].value=0;
            buf[i].num=0;
        }*/
        memset(buf,0,sizeof(buf));
        memset(c1,0,sizeof(c1));
        memset(c2,0,sizeof(c2));
        int sum=0;
        for(int i=0;i<zu;i++){
            scanf("%d%d",&buf[i].value,&buf[i].num);
            sum+=buf[i].value*buf[i].num;
        }
        //初始化c1,c2,c1是第一个括号的系数
        //注意,一个括号的系数为最大系数,因此用乘法
        //for(int i=0;i<=buf[0].num;i+=buf[0].value){
        for(int i=0;i<=buf[0].num*buf[0].value    ;i+=buf[0].value){
            c1[i]=1;
        }
        int endj=0;
        int endk=0;
        for(int i=2;i<=zu;i++){
            endj+=buf[i-2].num*buf[i-2].value;
            //这里必须是j++,因为jk的过程是合并括号的过程,每一项都要扫描
            //for(int j=0;j<=endj    ;j+=buf[i-2].value){
            for(int j=0;j<=endj    ;j++){
                endk=buf[i-1].num*buf[i-1].value;
                for(int k=0;k<=endk;k+=buf[i-1].value){
                    c2[j+k]+=c1[j];
                }
                
            }
            for(int j=0;j<=sum;j++){
                c1[j]=c2[j];
                c2[j]=0;
            }
        }
       
        //c1[i]存储的数字表示构成i的方法数目,因此平均直接找c[sum/2]即可,而不是找c[i]==sum/2
        if(sum%2==0 && c1[sum/2]!=0){
            //总数是偶数,并且可平分
            printf("%d %d\n",sum/2,sum/2);
        
            
        } else{
            
            for(int i=sum/2+1;i<=sum;i++){
                if(c1[i]!=0){
                    printf("%d %d\n",i,sum-i);
                    break;
                }
            }
            
        }
        
      
        
    
    }
    return 0;
}


0 0
原创粉丝点击