Equation
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 472 Accepted Submission(s): 137
Problem Description
Little 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.
Input
First 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.
Limits
1≤T≤30
0≤bricks number of each type≤100
Output
For 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 Input
3
1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2
0 3 3 0 3 0 0 0 0
Sample Output
Case #1: 2
Case #2: 6
Case #3: 2
Source
2016年中国大学生程序设计竞赛(杭州)
一共有36种情况
每个等式选/不选
O(236)
肯定T到爆
1+5=6 && 5+1=6 可以看做同一个等式选择了2次
暴力掉1+1,2+2,3+3,4+4
一共是
O(316∗24)
,复杂度有所改观,但是还是太高
然后考虑剪枝:
①: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;
}