HDU1045 DFS

思考一定少对着屏幕而是纸张和书本,不然效率会比较的低下。不要听歌!

真的是第一次凭着自己且没有看任何的东西做了一道dfs,感动。。。花费两个小时,继续加油鸭

整体收获:

1:还是对特殊情况的处理容易忽略,一开始写的代码不适用于T=1这种情况

2:一定要理清楚对矩阵的处理,传参数进dfs的时候,是不是存在换行的问题?

3:如果已经检测到(T,T)点(最后一个点),但是因为判断这个地方不能把参数传传进,那么就不会进入之后的dfs,就不会将cnt储蓄在num里面,这个

4:调试方法

本题花费较长时间之处:

1:在判断这个点是否可以放炮台的时候,仅仅判断了周围,没有判断这个点本身。考虑问题不严谨

2::检查到最后一个点的时候,没有储存cnt,判断结束程序

 

奉上我啰里啰唆的c++代码

#include <iostream>
#include <cstdio>
using namespace std;

int T;
char map[5][5];
int num[1000],n,cnt=0;//n记录的是有多少种方法,随着dfs将每个方法可以放的炮台的个数存在num里面
//cnt记录每个方法放置的炮台数 
bool is(int x,int y)//检查是否可以放置炮台
{
	if('p'==map[x][y] || 'X'==map[x][y]){
		return false;
	}
	int i;
	for(i=x-1;i>=1;i--){
		if('X'==map[i][y]){
			break;
		}else if('p'==map[i][y]){
			return false;
		}
	}
	for(i=x+1;i<=T;i++){
		if('X'==map[i][y]){
			break;
		}else if('p'==map[i][y]){
			return false;
		}
	}
	for(i=y-1;1<=i;i--){
		if('X'==map[x][i]){
			break;
		}else if('p'==map[x][i]){
			return false;
		}
	}
	for(i=y+1;i<=T;i++){
		if('X'==map[x][i]){
			break;
		}else if('p'==map[x][i]){
			return false;
		}
	}
	return true;
} 
???? 
void dfs(int x,int y,int cnt)//cnt是放置了多少炮台 
{
	if(T+1==x){//已经遍历结束 	
		num[n++]=cnt;
		return;
	}
	int i=0,j=0;
	for(i=x;i<=T;i++){//直接从上次放炮台的下一个地方开始检查 
		if(0==j)  j=y;//开始接着上次的地方遍历 
		else j=1;//上次那个地方的一行已经处理完毕,再重新开一行j=1 
		for(j;j<=T;j++){//判断是否到最后一个点,到最后一个点并别这个点不能放炮台,就dfs,结束程序
			if(T==i && T==j && !is(i,j)){
				dfs(i+1,1,cnt);
			}
			if(is(i,j)){//先检查是否能放炮台 
				map[i][j]='p';//放置炮台
				cnt++;//放置数+1; 
				if(T==j){
					dfs(i+1,1,cnt);
				}else{
					dfs(i,j+1,cnt);
				}
				cnt--;//放置数-1
				map[i][j]='.';//褪去标记 
			} 
		}
	} 
}

int main()
{
	while(cin >> T && T)
	{
		if(1==T){
			char temp;
			cin >> temp;
			cout << 1 << endl;
			continue;
		}
		
		int i,j;
		for(i=1;i<=T;i++){
			for(j=1;j<=T;j++){
				cin >> map[i][j];	
			} 
		}
		n=0,cnt=0;
		
		dfs(1,1,cnt);
		int max=0;
		for(i=0;i<n-1;i++){
			if(max<num[i]){
				max=num[i];
			}
		}
		cout << max << endl ;	
	} 
	return 0;
}




 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值