UVA 1603 Square Destroyer
Posted 日拱一卒 功不唐捐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA 1603 Square Destroyer相关的知识,希望对你有一定的参考价值。
https://vjudge.net/problem/UVA-1603
题意:
一个由火柴棒组成的正方形网络
现在拿走一些火柴
问在剩下的火柴里还要最少拿走几根火柴 才能够破坏所有的正方形
n=5,火柴棒最多60根,状态压缩
我们先只考虑没有拿走火柴棒的网格图
设base[i][j] 表示第i行第j列的正方形 需要火柴的状态
设squ[i]表示编号为i的正方形 需要火柴的状态
预处理出 边长为1的正方形
然后枚举他要往右下延伸的长度
然后枚举延伸之后的正方形的每个网格
squ[i]^=base[][]
1^1=0,如果一个火柴棒是两个小正方形的交接处,组成大的正方形之后,这个火柴棒不再参与构成正方形的边,正好异或掉
然后迭代加深搜索
估价函数:
设一开始拿走一些火柴棒之后的网格图 有状态为S 的火柴棒
枚举所有的正方形i
如果squ[i]&s == squ[i] 说明在S状态下,正方形i还没有被破坏
让s^=squ[i],need++
即暂时破坏这个正方形,继续枚举
如果枚举完后,当前拿走的火柴棒+need>限制,剪枝
因为所有的正方形都要被破坏,所以与枚举顺序无关
#include<cstdio> using namespace std; typedef long long LL; int n,cnt,maxd,tot; LL bit[61]; LL base[6][6],squ[56]; int get_ud(int i,int j) { return (2*n+1)*(i-1)+j-1; } int get_lr(int i,int j) { return (2*n+1)*(i-1)+j+n-1; } void build() { cnt=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { base[i][j]=0; base[i][j]|=bit[get_ud(i,j)]|bit[get_ud(i+1,j)]; base[i][j]|=bit[get_lr(i,j)]|bit[get_lr(i,j+1)]; squ[++cnt]=base[i][j]; } for(int siz=2;siz<=n;siz++) for(int i=1;i+siz-1<=n;i++) for(int j=1;j+siz-1<=n;j++) { squ[++cnt]=0; for(int w=0;w<siz;w++) for(int h=0;h<siz;h++) squ[cnt]^=base[i+w][j+h]; } } bool dfs(int d,LL state) { if(d==maxd) { for(int i=1;i<=cnt;i++) if((squ[i]&state)==squ[i]) return false; return true; } LL s=state; int need=0,del=0; for(int i=1;i<=cnt;i++) if((squ[i]&s)==squ[i]) { need++; s^=squ[i]; if(!del) del=squ[i]; } if(d+need>maxd) return false; for(int i=1;i<=tot;i++) if((del&bit[i-1])==bit[i-1]) if(dfs(d+1,state^bit[i-1])) return true; return false; } int main() { int T; scanf("%d",&T); bit[0]=1; for(int i=1;i<=60;i++) bit[i]=bit[i-1]<<1; int m,x; LL state; while(T--) { scanf("%d",&n); tot=2*n*(n+1); state=bit[tot]-1; scanf("%d",&m); while(m--) { scanf("%d",&x); state^=bit[x-1]; } build(); for(maxd=0;;maxd++) if(dfs(0,state)) break; printf("%d\n",maxd); } }
以上是关于UVA 1603 Square Destroyer的主要内容,如果未能解决你的问题,请参考以下文章