题目大意:给一个n*n的用单位长度的木棍拼起来的网格图,给每个木棍按图示编号,编号范围1~2*n*(n+1).现在已知图中已经去掉了k个木棍,求还要至少去掉几根木棍能使网格图中不存在正方形.即破坏图中所有的正方形.n不超过5.
题目分析:n太小了啦,直接爆搜!dancing links优化之.将之转化成一个重复覆盖的模型.
n*n的完全网格图中存在n*(n+1)*(2*n+1)/6个正方形.给每一个编号,然后小木棍的编号图中给了,就按那个来.然后小木棍为行,正方形为列,建图.
注意题目已经给定的k个木棍要去掉.首先那k个木棍覆盖的正方形是不用建图的,然后那k个表头也要删掉.
然后关于木棍编号破坏的正方形的关系.好像很复杂的样子,不过因为n太小了,然后我就打表了..不过好难数,数了一晚上....
正方形编号从1~n*(n+1)*(2*n+1)/6,顺序按边长递增从左上角到右下角.
详情请见代码:
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 6; const int M = 4000;//3300 const int NM = 56;//最大正方形个数 int n,K,num,ans; int h[M],s[M],u[M],d[M],l[M],r[M],col[M]; bool flag[NM],vis[NM]; int stk[NM]; int table[5][61][NM] = { { {0},{1,1},{1,1},{1,1},{1,1}, }, { {0},{2,1,5},{2,2,5},{2,1,5},{2,1,2},{2,2,5},{2,1,3}, {2,2,4},{2,3,5},{2,3,4},{2,4,5},{2,3,5},{2,4,5}, }, { {0},{3,1,10,14},{4,2,10,11,14},{3,3,11,14},{3,1,10,14}, {3,1,2,11},{3,2,3,10},{3,3,11,14},{3,1,4,12},{4,2,5,12,13}, {3,3,6,13},{4,4,10,12,14},{4,4,5,11,13},{4,5,6,10,12}, {4,6,11,13,14},{3,4,7,10},{4,5,8,10,11},{3,6,9,11}, {3,7,12,14},{3,7,8,13},{3,8,9,12},{3,9,13,14}, {3,7,12,14},{4,8,12,13,14},{3,9,13,14}, }, { {0},{4,1,17,26,30},{6,2,17,18,26,27,30},{6,3,18,19,26,27,30},{4,4,19,27,30}, {4,1,17,26,30},{4,1,2,18,27},{4,2,3,17,19},{4,3,4,18,26},{4,4,19,27,30}, {4,1,5,20,28},{5,2,6,20,21,29},{5,3,7,21,22,28},{4,4,8,22,29}, {6,5,17,20,26,28,30},{6,5,6,18,21,27,29},{6,6,7,17,19,20,22},{6,7,8,18,21,26,28},{6,8,19,22,27,29,30}, {4,5,9,17,23},{6,6,10,17,18,23,24},{6,7,11,18,19,24,25},{4,8,12,19,25}, {6,9,20,23,26,28,30},{6,9,10,21,24,27,29},{6,10,11,20,22,23,25},{6,11,12,21,24,26,28},{6,12,22,25,27,29,30}, {4,9,13,20,26},{5,10,14,20,21,27},{5,11,15,21,22,26},{4,12,16,22,27}, {4,13,23,28,30},{4,13,14,24,29},{4,14,15,23,25},{4,15,16,24,28},{4,16,25,29,30}, {4,13,23,28,30},{6,14,23,24,28,29,30},{6,15,24,25,28,29,30},{4,16,25,29,30}, }, { {0}, {5,1,26,42,51,55},{8,2,26,27,43,44,51,52,55},{9,3,27,28,42,43,44,51,52,55},{8,6,4,28,29,43,44,51,52,55},{5,5,29,44,52,55}, {5,1,26,42,51,55},{5,1,2,27,43,52},{5,2,3,26,28,44},{5,3,4,27,29,42},{5,4,5,28,43,51},{5,5,29,44,52,55}, {5,1,6,30,45,53},{8,2,7,30,31,45,46,53,54},{9,3,8,31,32,45,46,47,53,54},{8,4,9,32,33,46,47,53,54},{5,5,10,33,47,54}, {8,6,26,30,42,45,51,53,55},{8,6,7,27,31,43,46,52,54},{8,7,8,26,28,30,32,44,47},{8,8,9,27,29,31,33,42,45},{8,9,10,28,32,43,46,51,53},{8,10,29,33,44,47,52,54,55}, {5,6,11,26,34,48},{8,7,12,26,27,34,35,48,49},{9,8,13,27,28,35,36,48,49,50},{8,9,14,28,29,36,37,49,50},{5,10,15,29,37,50}, {9,11,30,34,42,45,48,51,53,55},{9,11,12,31,35,43,46,49,52,54},{9,12,13,30,32,34,36,44,47,50},{9,13,14,31,33,35,37,42,45,48},{9,14,15,32,36,43,46,49,51,53},{9,15,33,37,44,47,50,52,54,55}, {5,11,16,30,38,42},{8,12,17,30,31,38,39,42,43},{9,13,18,31,32,39,40,42,43,44},{8,14,19,32,33,40,41,43,44},{5,15,20,33,41,44}, {8,16,34,38,45,48,51,53,55},{8,16,17,35,39,46,49,52,54},{8,17,18,34,36,38,40,47,51},{8,18,19,35,37,39,41,45,48},{8,19,20,36,40,46,49,51,53},{8,20,37,41,47,50,52,54,55}, {5,16,21,34,45,51},{8,17,22,34,35,45,46,51,52},{9,18,23,35,36,45,46,47,51,52},{8,19,24,36,37,46,47,51,52},{5,20,25,37,47,52}, {5,21,38,48,53,55},{5,21,22,39,49,54},{5,22,23,38,40,50},{5,23,24,39,41,48},{5,24,25,40,49,53},{5,25,41,50,54,55}, {5,21,38,48,53,55},{8,22,38,39,48,49,53,54,55},{9,23,39,40,48,49,50,53,54,55},{8,24,40,41,49,50,53,54,55},{5,25,41,50,54,55}, } }; void init() { int i,c; memset(h,0,sizeof(h)); memset(s,0,sizeof(s)); c = n * (n + 1) * (2 * n + 1)/6; for(i = 0;i <= c;i ++) { u[i] = d[i] = i; l[i] = (i + c)%(c + 1); r[i] = (i + 1)%(c + 1); } num = c + 1; } void ins(int i,int j) { if(h[i]) { r[num] = h[i]; l[num] = l[h[i]]; l[r[num]] = r[l[num]] = num; } else { h[i] = num; l[num] = r[num] = num; } s[j] ++; u[num] = u[j]; d[num] = j; d[u[j]] = num; u[j] = num; col[num] = j; num ++; } void del(int c) { for(int i = d[c];i != c;i = d[i]) l[r[i]] = l[i],r[l[i]] = r[i]; } void recover(int c) { for(int i = u[c];i != c;i = u[i]) l[r[i]] = r[l[i]] = i; } int A() { int i,j,k,ret; ret = 0; memset(vis,false,sizeof(vis)); for(i = r[0];i;i = r[i]) { if(vis[i] == false) { ret ++; vis[i] = true; for(j = d[i];j != i;j = d[j]) for(k = r[j];j != k;k = r[k]) vis[col[k]] = true; } } return ret; } void dfs(int k) { if(k + A() >= ans) return; if(!r[0]) { ans = min(ans,k); return ; } int mn = M; int c,i,j; for(i = r[0];i;i = r[i]) { if(s[i] < mn) { mn = s[i]; c = i; } } for(i = d[c];i != c;i = d[i]) { del(i); for(j = r[i];j != i;j = r[j]) del(j); dfs(k + 1); for(j = l[i];j != i;j = l[j]) recover(j); recover(i); } } void build() { scanf("%d",&n); memset(flag,false,sizeof(flag)); scanf("%d",&K); int i,j; for(i = 1;i <= K;i ++) { scanf("%d",&stk[i]); for(j = 1;j <= table[n - 1][stk[i]][0];j ++) flag[table[n - 1][stk[i]][j]] = true; } init(); for(i = 1;i <= (n + 1) * n * 2;i ++) { for(j = 1;j <= table[n - 1][i][0];j ++) if(flag[table[n - 1][i][j]] == false) ins(i,table[n - 1][i][j]); } int nmgb = 0; for(i = 1;i <= n * (n + 1) * (n * 2 + 1)/6;i ++) if(flag[i]) l[r[i]] = l[i],r[l[i]] = r[i]; } void fuck() { ans = M; dfs(0); printf("%d\n",ans); } int main() { int t;scanf("%d",&t); while(t --) { build(); fuck(); } return 0; } //244K 0MS