您的位置:首页 > 其它

UVA 11214 Guarding the Chessboard 守卫棋盘(迭代加深+剪枝)

2015-07-31 10:45 513 查看
暴力,和八皇后很像,用表示i+j和i-j标记主对角线,但是还是要加一些的剪枝的。

1.最裸的暴搜

6.420s,差点超时

2.之前位置放过的就没必要在放了,每次从上一次放的位置开始放

0.400s

#include<cstdio>
#include<cstring>

const int maxn = 11;
char G[maxn][maxn];
int maxd;
int n,m;
bool visi[maxn],visj[maxn],vis1[maxn<<1],vis2[maxn<<1];

bool dfs(int d,int si,int sj)
{
if(d == maxd){
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++){
if(G[i][j] == 'X'&&!visi[i]&&!visj[j]&&!vis1[i+j]&&!vis2[i-j+10])
return false;
}
return true;
}
for(int i = si; i < n; i++){
for(int j = (i == si?sj:0); j < m; j++)
if(!visi[i] || !visj[j] || !vis1[i+j]|| !vis2[i-j+10]){
bool f1 = visi[i], f2 = visj[j], f3 = vis1[i+j], f4 = vis2[i-j+10];
visi[i] = visj[j] = vis1[i+j] = vis2[i-j+10] = true;
if(dfs(d+1,i,j))return true;
visi[i] = f1; visj[j] = f2; vis1[i+j] = f3; vis2[i-j+10] = f4;
}

}
return false;
}

int main()
{
int cas = 0;
while(scanf("%d%d",&n,&m),n){
for(int i = 0;i < n; i++) scanf("%s",G[i]);
for(maxd = 1; maxd < 5; maxd++){
memset(visi,0,sizeof(visi));
memset(visj,0,sizeof(visj));
memset(vis1,0,sizeof(vis1));
memset(vis2,0,sizeof(vis2));
if(dfs(0,0,0))break;
}
printf("Case %d: %d\n",++cas,maxd);
}
return 0;
}


第一种剪枝
3.可以逐行(或逐列)放置。还有一个剪枝就是最多放5个,所以maxd==4还没有解,直接输出5.

0.201s

#include<cstdio>
#include<cstring>

const int maxn = 11;
char G[maxn][maxn];
int maxd;
int n,m;
bool visi[maxn],visj[maxn],vis1[maxn<<1],vis2[maxn<<1];

bool dfs(int d,int si)
{
if(d == maxd){
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++){
if(G[i][j] == 'X'&&!visi[i]&&!visj[j]&&!vis1[i+j]&&!vis2[i-j+10])
return false;
}
return true;
}
for(int i = si; i < n; i++){
for(int j = 0; j < m; j++)
if(!visi[i] || !visj[j] || !vis1[i+j]|| !vis2[i-j+10]){
bool f1 = visi[i], f2 = visj[j], f3 = vis1[i+j], f4 = vis2[i-j+10];
visi[i] = visj[j] = vis1[i+j] = vis2[i-j+10] = true;
if(dfs(d+1,i+1))return true;
visi[i] = f1; visj[j] = f2; vis1[i+j] = f3; vis2[i-j+10] = f4;
}

}
return false;
}

int main()
{
int cas = 0;
while(scanf("%d%d",&n,&m),n){
for(int i = 0;i < n; i++) scanf("%s",G[i]);
for(maxd = 1; maxd < 5; maxd++){
memset(visi,0,sizeof(visi));
memset(visj,0,sizeof(visj));
memset(vis1,0,sizeof(vis1));
memset(vis2,0,sizeof(vis2));
if(dfs(0,0))break;
}
printf("Case %d: %d\n",++cas,maxd);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: