HDU-5937 Equation dfs+剪枝
HDU-5937 Equation
题意
给定1到9每个数字的个数,问最多能组成多少种不同的等式,\(1+2=3\)和\(2+1=3\)算做不同的等式。
分析
最多有36种不同的等式,对于数字\(x\),最多会消耗\(17-x\)个,所以输入的个数可以对\(17-x\)取\(min\)。
\(dfs\)爆搜,将\(1+2=3\)和\(2+1=3\)这种压成一个方案,就只有20个方案,dfs过程中判断若剩余数字全部用完或剩余可选的等式都选上都不大于当前答案就退出。
Code
#include<bits/stdc++.h>
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define per(i,n,x) for(int i=n;i>=x;i--)
#define sz(a) int(a.size())
#define rson mid+1,r,p<<1|1
#define pii pair<int,int>
#define lson l,mid,p<<1
#define ll long long
#define pb push_back
#define mp make_pair
#define se second
#define fi first
using namespace std;
const double eps=1e-8;
const int mod=1e9+7;
const int N=1e5+10;
const int inf=1e9;
int T;
int a[10],c[]={0,16,15,14,13,12,11,10,9,8};
int ans;
int x[40],y[40];
void dfs(int sum,int cur,int cnt){
if(sum/3+cnt<ans||(20-cur)*2+cnt<ans) return;
ans=max(ans,cnt);
for(int i=cur+1;i<=20;i++){
if(x[i]==y[i]){
if(a[x[i]]>=2&&a[x[i]+y[i]]){
a[x[i]]-=2,a[x[i]+y[i]]--;
dfs(sum-3,i,cnt+1);
a[x[i]]+=2,a[x[i]+y[i]]++;
}
}else{
if(a[x[i]]&&a[y[i]]&&a[x[i]+y[i]]){
a[x[i]]--,a[y[i]]--,a[x[i]+y[i]]--;
dfs(sum-3,i,cnt+1);
a[x[i]]++,a[y[i]]++,a[x[i]+y[i]]++;
}
if(a[x[i]]>=2&&a[y[i]]>=2&&a[x[i]+y[i]]>=2){
a[x[i]]-=2,a[y[i]]-=2,a[x[i]+y[i]]-=2;
dfs(sum-6,i,cnt+2);
a[x[i]]+=2,a[y[i]]+=2,a[x[i]+y[i]]+=2;
}
}
}
}
void solve(){
int sum=0;
ans=0;
for(int i=1;i<=9;i++){
scanf("%d",&a[i]);
a[i]=min(a[i],c[i]);
sum+=a[i];
}
if(sum>=108){
puts("36");
return;
}
dfs(sum,0,0);
printf("%d\n",ans);
}
int main(){
int tot=0;
rep(i,1,9) rep(j,i,9-i){
x[++tot]=i;
y[tot]=j;
}
scanf("%d",&T);
for(int cas=1;cas<=T;cas++){
printf("Case #%d: ",cas);
solve();
}
return 0;
}