首页 > 代码库 > HDU 5937 Equation(DFS+剪枝)

HDU 5937 Equation(DFS+剪枝)

题目链接 Equation

给定1-9这9个数字各自的卡片数,求能构成形如$i + j = k$的等式个数

等式中$i,j,k$必须都为个位数

若两个等式中$i,j,k$不完全相等,则这两个等式为不同的等式。

 

打表发现符合题意的等式有36个

那么通过01搜索状态数为$2^{36}$

TLE

我们求出若答案为36,每张卡片需求量$f[i]$

每次读入$a[i]$的时候

若对$i(1 <= i <= 9)$, 都有$a[i] >= f[i]$

则直接输出36

DFS的时候x为当前的等式用/不用

cnt为$1$到$x - 1$中用的等式个数

ans为当前保存答案的最大值

则当$cnt + 36 - x + 1 <= ans$的时候,剪枝

 

 

#include <bits/stdc++.h>using namespace std;#define rep(i, a, b)	for (int i(a); i <= (b); ++i)#define dec(i, a, b)	for (int i(a); i >= (b); --i)typedef long long LL;struct node{	int x, y, z;} c[105];int et = 0;int f[11];int a[11];int ans;int T;int ca = 0;vector <int> v;void dfs(int x, int cnt){	if (cnt + et - x + 1 <= ans) return;	if (x > et){		ans = max(ans, cnt);		return;	}	dfs(x + 1, cnt);	--a[c[x].x];	--a[c[x].y];	--a[c[x].z];	if (a[c[x].x] >= 0 && a[c[x].y] >= 0 && a[c[x].z] >= 0){		dfs(x + 1, cnt + 1);		++a[c[x].x];		++a[c[x].y];		++a[c[x].z];	}	else{		++a[c[x].x];		++a[c[x].y];		++a[c[x].z];	}	}	int main(){	rep(i, 1, 9) rep(j, 1, 9) rep(k, 1, 9){		if (i + j == k){			++et;			c[et].x = i;			c[et].y = j;			c[et].z = k;			++f[i], ++f[j], ++f[k];		}	}	scanf("%d", &T);	while (T--){		printf("Case #%d: ", ++ca); 		rep(i, 1, 9) scanf("%d", a + i);		bool fl = true;		rep(i, 1, 9) if (a[i] < f[i]){			fl = false;			break;		}		if (fl){			printf("%d\n", et);			continue;		}		ans = 0;		dfs(1, 0);		printf("%d\n", ans);	}	return 0;}

 

HDU 5937 Equation(DFS+剪枝)