http://acm.hdu.edu.cn/showproblem.php?pid=5937
题目大意:给出
1
−
9
1-9
1−9每个数字的个数,问最多能组成多少个不同的形如
a
+
b
=
c
a+b=c
a+b=c的式子。(
1
+
2
=
32
+
1
=
31
+
4
=
5
1+2=3 2+1=3 1+4=5
1+2=32+1=31+4=5这些都视为不同情况)
思路:真的爆搜就过了,只需要一个特别简单的剪枝。通过枚举发现最多只有
36
36
36个式子,且数字
i
i
i只需要用到
36
−
i
36-i
36−i次。直接爆搜
O
(
2
36
)
O(2^{36})
O(236)会超时,需要一个小剪枝:假设我们当前该判断第
c
u
r
cur
cur个式子,且有
n
u
m
num
num个式子成立,答案为
a
n
s
ans
ans,那么当
36
−
c
u
r
+
n
u
m
<
=
a
n
s
36-cur+num<=ans
36−cur+num<=ans时,就没有搜下去的必要了。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
int a[10],d[40][3],vis[12],ans;
void init()
{
int cnt=0;
for(int i=1;i<=9;i++)
{
for(int j=1;j+i<=9;j++)
{
d[cnt][0]=i;
d[cnt][1]=j;
d[cnt++][2]=i+j;
vis[i]++;vis[j]++;vis[i+j]++;
}
}
//cout<<cnt<<endl; 36个
}
void dfs(int cur,int num)
{
if(36-cur+num<=ans||cur==36)
return ;
--a[d[cur][0]],--a[d[cur][1]],--a[d[cur][2]];
if(a[d[cur][0]]>=0&&a[d[cur][1]]>=0&&a[d[cur][2]]>=0)
{
ans=max(ans,num+1);
dfs(cur+1,num+1);
}
++a[d[cur][0]],++a[d[cur][1]],++a[d[cur][2]];
dfs(cur+1,num);
}
int main()
{
init();
// for(int i=1;i<=9;i++)
// cout<<vis[i]<<' '; 17-i 个即可
int t;
scanf("%d",&t);
int times=0;
while(t--)
{
bool flag=0;
for(int i=1;i<=9;i++)
{
scanf("%d",&a[i]);
if(a[i]<17-i)
flag=1;
else
a[i]=17-i;
}
if(!flag)
printf("Case #%d: %d\n",++times,36);
else
{
ans=0;
dfs(0,0);
printf("Case #%d: %d\n",++times,ans);
}
}
return 0;
}