在精确覆盖的基础上只修改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