四子连棋【黄金题】【宽搜】

http://codevs.cn/problem/1004/

思路:

我的思路是,将棋盘用一个17个大小的字符串表示,最后一位表示黑子(白子)执棋。使用map<string,bool>判断某一棋盘是否已经存在了。

需要注意的是,棋盘的移动中,左右移动需要额外判断一下是不是边界棋子,比如第3号棋子的右边4号棋子其实是下一行的起始棋子。

#include<iostream>
#include<cmath> 
#include<queue>
#include<string>
#include<map>
using namespace std;

string chess0="";
map<string,bool> mp;
queue<string>q;

bool target(string  str){
	//判断四行 
	for(int i=0;i<16;i+=4){
		char top=str[i+0];
		if(top==str[i+1]&&top==str[i+2]&&top==str[i+3])return true;
	}
	//判断四列
	for(int i=0;i<4;i++){
		char top=str[i];
		if(top==str[i+4]&&top==str[i+8]&&top==str[i+12])return true;
	} 
	char top=str[0];
	if(top==str[5]&&top==str[10]&&top==str[15])return true;
	top=str[3];
	if(top==str[6]&&top==str[9]&&top==str[12])return true;
	return false;
}
void show(string &str){
//	cout<<endl;
//	for(int i=0;i<16;i+=4){
//		for(int j=0;j<4;j++){
//			cout<<str[i+j];
//		}cout<<endl;
//	}
//	cout<<str[16]<<endl;
}
bool move(string str){
	
//	cout<<"*****************************";
	show(str);
//	cout<<"*****************************"<<endl;
	char b=str[16];
	for(int i=0;i<16;i++){
		if(str[i]=='O'){
			if(i-4>=0&&str[i-4]==b){//上 
				string new_chess=str;
				new_chess[i]=b;
				new_chess[i-4]='O';
				if(b=='B')new_chess[16]='W';
				else new_chess[16]='B';
				
				if(mp.count(new_chess)==0){
					mp[new_chess]=false;
					if(target(new_chess)){
						show(new_chess);
						return true;
					}
					q.push(new_chess);
				}
				show(new_chess);
			} 
			if(i-1>=0&&(i-1)%4!=3&&str[i-1]==b){//左 
				string new_chess=str;
				new_chess[i]=b;
				new_chess[i-1]='O';
				if(b=='B')new_chess[16]='W';
				else new_chess[16]='B';
				
				if(mp.count(new_chess)==0){
					mp[new_chess]=false;
					if(target(new_chess)){
						show(new_chess);
						return true;
					}
					q.push(new_chess);
				}
				show(new_chess);
			} 
			if(i+4<16&&str[i+4]==b){//下 
				string new_chess=str;
				new_chess[i]=b;
				new_chess[i+4]='O';
				if(b=='B')new_chess[16]='W';
				else new_chess[16]='B';
				
				if(mp.count(new_chess)==0){
					mp[new_chess]=false;
					if(target(new_chess)){
						show(new_chess);
						return true;
					}
					q.push(new_chess);
				}
				show(new_chess);
			} 
			if(i+1<16&&(i+1)%4!=0&&str[i+1]==b){//右 
				string new_chess=str;
				new_chess[i]=b;
				new_chess[i+1]='O';
				if(b=='B')new_chess[16]='W';
				else new_chess[16]='B';
				
				if(mp.count(new_chess)==0){
					mp[new_chess]=false;
					if(target(new_chess)){
						show(new_chess);
						return true;
					}
					q.push(new_chess);
				}
				show(new_chess);
			} 
		} 
	} 
	return false;
} 


int main(){	
	//初始化棋盘 
	string str;
	int t=4;
	while(t--) {
		cin>>str;chess0+=str;
	}	
	mp[chess0+"B"]=false;
	mp[chess0+"W"]=false;
	
	
	int ans=0;
	q.push(chess0+"W");
	q.push(chess0+"B");
	if(target(chess0+"B")||target(chess0+"W")){
		cout<<100<<endl;
		return 0;
	}

	while(1){
		
		ans++;
		//cout<<ans<<endl<<endl;
		int len=q.size();
		while(len--){
			string top=q.front();q.pop();
			if(move(top)){
				cout<<ans<<endl;
				return 0;
			}
		}			
	}
	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值