ZOJ 2292 Anti-bug before Chinese Valentine's Day(DFS+剪枝)

37 篇文章 1 订阅

剪枝:

1.当前用的杀虫剂的个数超过了当前最优值,剪掉

2.当前的点上有虫子,必须要放杀虫剂,因为杀虫剂的范围是lawn[i][j],law[i][j+1],law[i+1][j],law[i+1][j+1],如果不放的话,后面就没有机会杀掉这个位置上的虫子了,想想就明白了

3.如果当前位置放了杀虫剂,那么可以直接跳到ci,cj+2位置,因为杀虫剂的范围内已经没有虫子了,没有必要.

4.如果下一行完全没有虫子,那么可以跳到ci+2,0的位置再开始,理由同上

#include <iostream>
#include <cstdio>
#include <memory.h>
using namespace std;
const int maxn=8;
char lawn[maxn][maxn];
int n,m,ans;
int di[]={0,0,1,1},dj[]={0,1,0,1};

void dfs(int ci,int cj,int left,int cnt){
	if(left<=0){
		ans=min(ans,cnt);
		return;
	}else if(cnt>=ans||ci>=n)return;
	int kill=0;
	bool put[4]={0};
	for (int i=0;i<4;++i){
		int ni=ci+di[i],nj=cj+dj[i];
		if(ni>=0&&ni<n&&nj>=0&&nj<m&&lawn[ni][nj]=='o'){
			put[i]=1;
			kill++;
			lawn[ni][nj]='.';
		}
	}
	if(kill){
		if(cj+2<m)dfs(ci,cj+2,left-kill,cnt+1);
		else{
			if(ci+1<n){//边界
				int i;
				for (i=0;i<m;++i){//判断下一行是否都是空的
					if(lawn[ci+1][i]=='o')break;
				}
				if(i==m)dfs(ci+2,0,left-kill,cnt+1);
				else dfs(ci+1,0,left-kill,cnt+1);
			}else{
				dfs(ci+1,0,left-kill,cnt+1);
			}
		}
		//还原现场
		for (int i=0;i<4;++i){
			if(put[i]){
				int ni=ci+di[i],nj=cj+dj[i];
				lawn[ni][nj]='o';
			}
		}
	}
	if(lawn[ci][cj]=='.'){//不放杀虫剂的前提是这个点上没有虫子
		if(cj+1<m)dfs(ci,cj+1,left,cnt);
		else{
			if(ci+1<n){
				int i;
				for (i=0;i<m;++i){//判断下一行是否都是空的
					if(lawn[ci+1][i]=='o')break;
				}
				if(i==m)dfs(ci+2,0,left,cnt);
			    else dfs(ci+1,0,left,cnt);
			}else{
				dfs(ci+1,0,left,cnt);
			}
		}
	}
}
int main(){
	while (scanf("%d%d",&n,&m)){
		if(!n&&!m)break;
		int cnt=0;
		ans=16;
		for (int i=0;i<n;++i){
			for (int j=0;j<m;++j){
				cin>>lawn[i][j];
				if(lawn[i][j]=='o')cnt++;
			}
		}
		dfs(0,0,cnt,0);
		printf("%d\n",ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值