标签:
在精确覆盖的基础上只修改remove() 和resume() 就好了,每次选中一行,只把这一行对应的列以及这一行删除即可。
很显然的,这样降低了矩阵缩小的速度,但是出现A*优化的补救方法,H()是在VJ上扒下来的,233。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #include <stack> #include <map> #pragma comment(linker, "/STACK:1024000000") #define EPS (1e-8) #define LL long long #define ULL unsigned long long #define _LL __int64 #define INF 0x3f3f3f3f #define Mod 100007 using namespace std; const int MAXCLOUM = 230,MAXROW = 230,MAXPOINT = 230*230; bool MARKCLOUM[MAXCLOUM]; int sta[MAXROW],sta_anw;//答案栈以及栈内元素个数 int SIZE[MAXCLOUM];//每一列元素个数,不包括虚拟列指针 int PRE[MAXROW];//每一行最后加入的元素位置,初始为-1. int C[MAXCLOUM];//每一列的头指针的位置 int ROW[MAXPOINT],COL[MAXPOINT];//每个元素的行列坐标 int L[MAXPOINT],R[MAXPOINT],U[MAXPOINT],D[MAXPOINT];//每个元素的四个指针 int Top;//第一个未分配元素的地址 inline int Creat(int row,int col) { COL[Top] = col; ROW[Top] = row; U[Top] = Top; D[Top] = Top; L[Top] = Top; R[Top] = Top; return Top++; } void Init(int row,int col) { sta_anw = 0; Top = 0; C[0] = Creat(0,0); for(int i = 1; i <= col; ++i) { C[i] = Creat(0,i); R[C[i]] = R[C[i-1]]; L[R[C[i-1]]] = C[i]; R[C[i-1]] = C[i]; L[C[i]] = C[i-1]; SIZE[i] = 0; } memset(PRE,-1,sizeof(PRE)); } void Insert(int row,int col) { //cout<<"row = "<<row<<" col = "<<col<<endl; int now = Creat(row,col); D[U[C[col]]] = now; U[now] = U[C[col]]; D[now] = C[col]; U[C[col]] = now; ++SIZE[col]; if(PRE[row] != -1) { L[R[PRE[row]]] = now; R[now] = R[PRE[row]]; L[now] = PRE[row]; R[PRE[row]] = now; } PRE[row] = now; } void Remove(int c) { for(int i = D[c]; i != c; i = D[i]) { L[R[i]] = L[i]; R[L[i]] = R[i]; } } void Resume(int c) { for(int i = U[c]; i != c; i = U[i]) { L[R[i]] = i; R[L[i]] = i; } } int Min; int H() { memset(MARKCLOUM,false,sizeof(MARKCLOUM)); int i,j,k,ans = 0; for(i = R[C[0]];i != C[0] ;i = R[i]) { if(MARKCLOUM[COL[i]]) continue; MARKCLOUM[COL[i]] = true; ans++; for(j = D[i];j != i; j = D[j]) { for(k = R[j];k != j ; k = R[k]) { MARKCLOUM[COL[k]] = true; } } } return ans; } bool Dance(int dis) { int now,i,j; if(dis+H() >= Min) return false; if(R[C[0]] == C[0]) return Min = dis,true; for(i = now = R[C[0]];i != C[0];i = R[i]) { if(SIZE[COL[i]] < SIZE[COL[now]]) now = i; } for(i = D[now]; i != now; i = D[i]) { Remove(i); for(j = R[i]; j != i; j = R[j]) Remove(j); Dance(dis+1); for(j = L[i]; j != i; j = L[j]) Resume(j); Resume(i); } return false; } int Map[20][20]; int main() { //freopen("data.in","r",stdin); int n,m,i,j,x,y,k,l; while(scanf("%d %d",&n,&m) != EOF) { for(i = 0;i < n; ++i) { for(j = 0;j < m; ++j) scanf("%d",&Map[i][j]); } scanf("%d %d",&x,&y); int sum = 0; for(i = 0;i < n; ++i) for(j = 0;j < m; ++j) if(Map[i][j]) Map[i][j] = ++sum; Init(n*m,sum); Min = min(sum,((n+x-1)/x)*((m+y-1)/y)); sum = 0; for(i = 0;i <= n-x; ++i) for(j = 0;j <= m-y; ++j) { sum++; for(l = 0;l < x; ++l) { for(k = 0;k < y; ++k) { if(Map[i+l][j+k]) Insert(i*m+j,Map[i+l][j+k]); } } } Dance(0); printf("%d\n",Min); } return 0; }
标签:
原文地址:http://blog.csdn.net/zmx354/article/details/43148383