您的位置:首页 > 其它

可重复覆盖的DLX

2015-01-26 08:33 127 查看
在精确覆盖的基础上只修改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 = 300,MAXROW = 300,MAXPOINT = MAXCLOUM*MAXROW;

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;//第一个未分配元素的地址
int Min;//记录最优解

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)
{
Min = MAXCLOUM;
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 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);
sta[sta_anw++] = ROW[i];
Dance(dis+1);
sta_anw--;
for(j = L[i]; j != i; j = L[j])
Resume(j);
Resume(i);
}

return false;
}

char Map[20][20];
int vis[20][20];

int jx[] = {-1, 0, 0, 1};
int jy[] = { 0,-1, 1, 0};

int Cal(int x,int y,int dir)
{
while(1)
{
x += jx[dir];
y += jy[dir];

if(Map[x][y] == '*')
return -1;
if(vis[x][y])
return vis[x][y];

}
}

int main()
{
int ans,n,m,i,j,k,tmp;

while(scanf("%d %d",&n,&m) != EOF)
{
for(i = 1;i <= n; ++i)
scanf("%s",Map[i]+1);

memset(vis,0,sizeof(vis));

for(i = 1,ans = 0;i <= n; ++i)
for(j = 1;j <= m; ++j)
if(Map[i][j] == '#')
vis[i][j] = ++ans;

Init(256,ans);

for(ans = 1,i = 1;i <= n; ++i)
for(j = 1;j <= m; ++j)
{
if(Map[i][j] == '.')
{
for(k = 0;k < 4; ++k)
{
if((tmp = Cal(i,j,k)) != -1)
{
Insert(ans,tmp);
}
}
ans++;
}
}

Dance(1);

printf("%d\n",Min-1);
}

return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: