题意:
给定一个火柴棒拼成的方格阵,然后去掉一些火柴棒,问至少再去掉几根火柴棒能够让图中一个正方形都没有。
思路:
1. 由于题目中给定了 n 的范围,2 * n * (n + 1) <= 60 -> 所以能够保证所有的火柴用 long long的位运算表示;
2. 启发式函数 h 的计算需要考量:如果删除了某个方阵的一个边,则能够保证 h(s1) <= h(s2) + C(s1, s2),其中 C(s1, s2) = 1,h(s1) - h(s2) <= 1;
3. 各种位运算的范围要明确,如 1<<i 前面要加上long long 修饰方能得到正确的结果
代码:
#include#include #include #include using namespace std; const int INFS = 0x7fffffff; int N,C,E,bound; long long squ[100],xiao[6][6]; bool flag; long long get2(int i) { return ((long long)1<<(i-1)); } int getnumber1(int i,int j) { return (2*N+1)*(i-1)+j; } int getnumber2(int i,int j) { return (2*N+1)*(i-1)+j+N; } void build() { C=0; memset(xiao,0,sizeof(xiao)); int i,j; for(i=1;i<=N;i++) for(j=1;j<=N;j++) { xiao[i][j]|=get2(getnumber1(i,j))|get2(getnumber1(i+1,j)); xiao[i][j]|=get2(getnumber2(i,j))|get2(getnumber2(i,j+1)); squ[C++]=xiao[i][j]; } for(int size=2;size<=N;size++) { for(i=1;i+size-1<=N;i++) { for(j=1;j+size-1<=N;j++) { squ[C]=0; for(int a=0;a bound) return de+h; int news=INFS; for(int i=1;i<=E;i++) { if(u&get2(i)) { int b=dfs(state^get2(i),de+1); if(flag) return b; news=min(b,news); } } return news; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d",&N); build(); E=2*N*(N+1); int k; long long state=((long long)1<