HDU5937 Equation 【DFS+剪枝】

来源:互联网 发布:米思米2016选型软件 编辑:程序博客网 时间:2024/06/17 20:39
EquationTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 472    Accepted Submission(s): 137Problem DescriptionLittle Ruins is a studious boy, recently he learned addition operation! He was rewarded some number bricks of 1 to 9 and infinity bricks of addition mark '+' and equal mark '='.Now little Ruins is puzzled by those bricks because he wants to put those bricks into as many different addition equations form x+y=z as possible. Each brick can be used at most once and x, y, z are one digit integer.As Ruins is a beginer of addition operation, x, y and z will be single digit number.Two addition equations are different if any number of x, y and z is different.Please help little Ruins to calculate the maximum number of different addition equations.InputFirst line contains an integer T, which indicates the number of test cases.Every test case contains one line with nine integers, the ith integer indicates the number of bricks of i.Limits1≤T≤300≤bricks number of each type≤100OutputFor every test case, you should output 'Case #x: y', where x indicates the case number and counts from 1 and y is the result.Sample Input31 1 1 1 1 1 1 1 12 2 2 2 2 2 2 2 20 3 3 0 3 0 0 0 0Sample OutputCase #1: 2Case #2: 6Case #3: 2Source2016年中国大学生程序设计竞赛(杭州)

一共有36种情况
每个等式选/不选 O(236) 肯定T到爆

1+5=6 && 5+1=6 可以看做同一个等式选择了2次
暴力掉1+1,2+2,3+3,4+4
一共是O(31624),复杂度有所改观,但是还是太高

然后考虑剪枝:
①:maxAns=所有数字个数/3,选出的最大等式数ans==maxAns,不可能有更大了,直接返回
②:如果当前已经选择了的等式数+剩下可以选择的等式数<=ans,不可能比ans大了,直接退出这次dfs

#include<iostream>#include<cstdlib>#include<cstdio>#include<string>#include<vector>#include<deque>#include<queue>#include<algorithm>#include<set>#include<map>#include<stack>#include<ctime>#include<string.h>#include<math.h>#include<list>using namespace std;#define ll long long#define pii pair<int,int>const int inf = 1e9 + 7;const int N = 1e5+5;inline int read(){    int x;    char ch;    while(!isdigit(ch=getchar()));    x=ch-'0';    while(isdigit(ch=getchar())){        x=x*10+ch-'0';    }    return x;}int num[10];int maxAns=0;int tn[4][3]={{1,1,2},{2,2,4},{3,3,6},{4,4,8}};//1+1=2,2+2=4,......int ans=0;void dfs(int i,int j,int k,int canSelect){//当前选到i+j这个等式,(i<j),k=已经选了的等式数,canSelect=剩下的能选择的最大等式数    if(ans>=maxAns||canSelect+k<=ans){        return;    }    if(i+j>9){        i+=1;        j=i+1;    }    if(i>=5){        int n1=num[1],n2=num[2],n3=num[3],n4=num[4],n6=num[6],n8=num[8];        for(int z=0,end=1<<4;z<end;++z){            int tk=k;            num[1]=n1,num[2]=n2,num[3]=n3,num[4]=n4,num[6]=n6,num[8]=n8;            for(int x=0;x<4;++x){                if(z&(1<<x)){                    --num[tn[x][0]];                    --num[tn[x][1]];                    --num[tn[x][2]];                    if(num[tn[x][0]]>=0&&num[tn[x][1]]>=0&&num[tn[x][2]]>=0){                        ++tk;                    }                    else{                        tk=-1;                        break;                    }                }            }            ans=max(tk,ans);        }        num[1]=n1,num[2]=n2,num[3]=n3,num[4]=n4,num[6]=n6,num[8]=n8;        return;    }    int&a=num[i],&b=num[j],&c=num[i+j];    --a,--b,--c;    if(a>=0&&b>=0&&c>=0){        dfs(i,j+1,k+1,canSelect-2);        --a,--b,--c;        if(a>=0&&b>=0&&c>=0){            dfs(i,j+1,k+2,canSelect-2);        }        ++a,++b,++c;    }    ++a,++b,++c;    dfs(i,j+1,k,canSelect-2);}int main(){    //freopen("/home/lu/Documents/r.txt","r",stdin);    //freopen("/home/lu/Documents/w.txt","w",stdout);    int T;    scanf("%d",&T);    for(int t=1;t<=T;++t){        maxAns=0;        for(int i=1;i<=9;++i){            scanf("%d",&num[i]);            maxAns+=num[i];        }        maxAns/=3;        ans=0;        dfs(1,2,0,36);        printf("Case #%d: %d\n",t,ans);    }    return 0;}
1 0
原创粉丝点击