搜索 POJ 2870 Light Up

原创 2016年08月30日 22:40:55

题目链接:  POJ 2870 Light Up

分析:

求最小步数,首先想到了IDA*,但是写了1个多小时,严重超时。仔细思考后发现,步数可以达到20步以上,比如以下这个样例需要25步:

7 7
24
1 2 -1
1 4 -1
1 6 -1
2 1 -1
2 3 -1
2 5 -1
2 7 -1
3 2 -1
3 4 -1
3 6 -1
4 1 -1
4 3 -1
4 5 -1
4 7 -1
5 2 -1
5 4 -1
5 6 -1
6 1 -1
6 3 -1
6 5 -1
6 7 -1
7 2 -1
7 4 -1
7 6 -1
所以在用IDA*之前,还是要想一想步数会不会太多。

谈一谈朴素的深搜——

地图类型的搜索(例如数独) 一般都是采用一格一格的搜索,有时可以改变顺序(例如数独很多时候需要从条件最多的格子入手)。

如果按顺序搜索会有一个剪枝的方便之处,本题就用到了——后面的行极有可能无法影响前面的格子。


本题代码如下:

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>

#define xx first
#define yy second
#define LL long long
#define CLEAR(xxx) memset(xxx,0,sizeof(xxx))
#define INTpair pair<int,int>

using namespace std;
const int maxn=20,inf=1e9;

int n,m,B,s[maxn][maxn],lit[maxn][maxn];
bool lamp[maxn][maxn];
int ans;
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
vector<INTpair> v;

void Change(int x,int y,int type){
	//点亮(type==1)或者 熄灭(type==-1)这个点 
	int i;
	lamp[x][y]= (type==1);
	for(i=y;i>0&&s[x][i]==-2;i--)lit[x][i]+=type;
	for(i=y+1;i<=m&&s[x][i]==-2;i++)lit[x][i]+=type;
	for(i=x-1;i>0&&s[i][y]==-2;i--)lit[i][y]+=type;
	for(i=x+1;i<=n&&s[i][y]==-2;i++)lit[i][y]+=type;
}

bool check1(){  //检查带编号的墙 ,是否满足要求 
	int i,j;
	for(i=0;i<v.size();i++){
		int x=v[i].xx,y=v[i].yy,cnt=0;
		for(j=0;j<4;j++)
			if(lamp[x+dx[j]][y+dy[j]])cnt++;
		if(cnt!=s[x][y]) return false;
	}
	return true;
} 

bool check2(){  
	//剪枝1: 检查带编号的墙 ,是否已经有超过要求的,有返回false 
	int i,j;
	for(i=0;i<v.size();i++){
		int x=v[i].xx,y=v[i].yy,cnt=0;
		for(j=0;j<4;j++)
			if(lamp[x+dx[j]][y+dy[j]])cnt++;
		if(cnt>s[x][y]) return false;
	}
	return true;
} 

bool check3(int x,int y){  
	//检查(x,y)这个点会不会和已经有的灯冲突 
	int i;
	for(i=y-1;i>0&&s[x][i]==-2;i--)if(lamp[x][i])return false;
	for(i=x-1;i>0&&s[i][y]==-2;i--)if(lamp[i][y])return false;
	return true;
}

bool ALL(){  //检查是否全部点亮 
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			if(s[i][j]==-2&&!lit[i][j])return false;
	return true;
}

bool Above(int x,int y){
	/*  强剪枝: 
		检查墙(x,y) ,如果他的正上方还有没点亮的,那之后也没法点亮 
	*/ 
	for(int i=1;i<x;i++)
		if(s[i][y]==-2&&!lit[i][y]) return true;
	return false;
}

void PrintMap(){
	cout<<"*********&&&&&&&&&&************"<<endl;
	for(int i=1;i<=n;i++,cout<<endl)
		for(int j=1;j<=m;j++)cout<<lamp[i][j]<<" ";
	cout<<"*********&&&&&&&&&&************"<<endl;
}

void DFS(int x,int y,int dep){ //当前讨论(x,y)这个点,已经放了dep个灯 
	//cout<<x<<" "<<y<<" "<<dep<<endl;
	if(dep>=ans) return ;
	if(!check2()) return ;
	if(y==1&&x==n+1&&check1()&&ALL()){
		ans=min(ans,dep);
		//PrintMap();
		return ;
	}
	if(x>n||y>m) return ;
	if(s[x][y]>=-1){    //搜到墙了 
		if(x>1&&s[x-1][y]==-2&& Above(x,y))return;
		if(y<m) DFS(x,y+1,dep);
		else DFS(x+1,1,dep);
	}
	else {
		if(y<m)DFS(x,y+1,dep);
		else DFS(x+1,1,dep);
		if(check3(x,y)){
			Change(x,y,1);
			if(y<m)DFS(x,y+1,dep+1);
			else DFS(x+1,1,dep+1);
			Change(x,y,-1);
		}
	}
}

int main(){
	int i,j,x,y;
	while(cin>>n>>m){
		if(!n&&!m) return 0;
		CLEAR(s);CLEAR(lit); CLEAR(lamp);
		for(i=1;i<=n;i++)
			for(j=1;j<=m;j++)s[i][j]=-2;
		cin>>B;
		v.clear();
		for(i=1;i<=B;i++){
			cin>>x>>y;
			cin>>s[x][y];
			if(s[x][y]!=-1)v.push_back(make_pair(x,y));
		}
		ans=inf;
		DFS(1,1,0);
		if(ans==inf)cout<<"No solution"<<endl;
		else cout<<ans<<endl; 
	}
	return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

poj2870Light Up(迭代加深搜索)

Light Up Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 754   Accept...

poj 2870

Light UpTime Limit: 1000MS Memory Limit: 65536KTotal Submissions: 459 Accepted: 181DescriptionLight ...
  • fp_hzq
  • fp_hzq
  • 2011-03-19 11:35
  • 1147

Light OJ 1132 Summing up Powers 矩阵快速幂

题目大意: 求(1K + 2K + 3K + ... + NK) % 232 的值

[Economist] iPhones make Chinese eyes light up iPhone使中国人欢呼雀跃

Apple in China 苹果在中国 iPhones make Chinese eyes light up iPhone手机使中国人欢呼雀跃 Apple doesn’t just ...

STM32 Tutorial: #2 Light up LEDs

I skipped the steps about creating a project in CoIDE because it’s too simple to post.My first progr...
  • igame
  • igame
  • 2017-07-30 15:05
  • 255

POJ - 3087 Shuffle'm Up(15.10.10 搜索专题)模拟

思路:简单题,洗牌后的顺序和分离的方法都是确定的,直接模拟

[kuangbin带你飞]专题一 简单搜索 G - Shuffle'm Up poj 3087

G - Shuffle'm Up Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d &...

zoj 2870 || poj 3304 Segments

这个题也是,刚开始学计算几何,那个分类就有了,但是一直没看懂,刚才又看了一次,YY了下,懂了。 求是否存在一条直线使得其他直线在它上面的投影有共同交点,如果存在,做这条直线的垂线,那么肯定和每个线段...

POJ3087-Shuffle'm Up

  • 2011-07-29 20:37
  • 11KB
  • 下载

POJ 3533 Light Switching Game

POJ 3533 Light Switching Game 三维的翻硬币游戏,就是传说的Nim积。 知道这个并且有模板,万事不愁。。 #include #include #include #in...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)