简单搜索题型

棋盘问题

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。

input

输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。

output

对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。

Sample Input

2 1
#.
.#
4 4
…#
…#.
.#…
#…
-1 -1

Sample Output

2
1

分析

该题令我困扰的点在于,由于棋子本身完全相同,所以不存在全排列的情况,以致于我一直都在考虑如何避免全排列。解决这种情况的办法是,在单行之间进行搜索
代码如下

#include<stdio.h>
#include<string.h>
int ans=0,n,num=0,x[10],y[10],k,h=0;char chess[10][10];
void dfs(int h)  //搜素第h行 
{
	if(num==k)
	{
		ans++;
		return;
	}
	if(h==n)
	return;
	for(int j=0;j<n;j++)
	{
		if(chess[h][j]=='.' || y[j]==1)
		continue;
		if(x[h]==1)
		break;
		if(chess[h][j]=='#')
		{
			x[h]=1;y[j]=1;num++;
			dfs(h+1);
		}
		num--;
		x[h]=0;y[j]=0;
	}
	dfs(h+1);
}
int main()
{
	while(scanf("%d%d",&n,&k))
	{
		ans=0,num=0,h=0;
		memset(x,0,sizeof(x));
		memset(y,0,sizeof(y));
		memset(chess,0,sizeof(chess));
		if(n==-1 && k==-1)
		break;
		for(int i=0;i<n;i++)
		{
			scanf("%s",chess[i]);
		}
		dfs(h);
		printf("%d\n",ans);
	}
}

迷宫问题

题目

定义一个二维数组:

int maze[5][5] = {

0, 1, 0, 0, 0,

0, 1, 0, 1, 0,

0, 0, 0, 0, 0,

0, 1, 1, 1, 0,

0, 0, 0, 1, 0,

};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

Input

一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
Output
左上角到右下角的最短路径,格式如样例所示。

Sample Input

0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

Sample Output

(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)

分析

对路径的一个分析,由于是最短路径,直接考虑广度优先搜索。主要思路是定义一个结构和队列,队列里有一个变量是上一个队列站的位置

标程

#include<stdio.h>
#include<string.h>
int maze[10][10],next[4][2]={{1,0},{0,1},{-1,0},{0,-1}},px,py,head=1,tail=2,flag=1;
struct n
{
	int x,y,before;
}a[10000];
void put(int b)
{
	if(a[b].before!=0)
	put(a[b].before);
	printf("(%d, %d)\n",a[b].x,a[b].y);
}
void bfs(int x,int y,int head)
{
	a[head].x=x;a[head].y=y;
	maze[0][0]=1;a[1].before=0; 
	while(head<tail)
	{
		for(int i=0;i<4;i++)
		{
			px=a[head].x+next[i][0];
			py=a[head].y+next[i][1];
			if(px<0 || px>4 || py<0 || py>4 || maze[px][py]==1)
			continue;
			if(maze[px][py]==0)
			{
				a[tail].x=px;a[tail].y=py;a[tail].before=head;
				maze[px][py]=1;
				tail++; 
			}
		//	printf("px=%d,py=%d\n",px,py);
		//	printf("1  head=%d,tail=%d\n",head,tail);
			if(px==4 && py==4)
			{
				//printf("tail=%d\n",tail);
				put(tail-1);flag=0;break;
			}
			
			
		}
	
		head++;
	//	printf("2  head=%d,tail=%d\n",head,tail);
			if(flag==0)
		break;
	}
	
}
int main()
{
	for(int i=0;i<5;i++)
	{
		for(int j=0;j<5;j++)
		scanf("%d",&maze[i][j]);
	}
	bfs(0,0,1);
} 

早华寅的峡谷旅行

早队喜欢和小学妹一起旅游。由于资金有限,只能去峡谷 (一个二维数组) 旅游,但是他可以传送到
峡谷的任意一个位置,现在他想知道针对任意的传送位置 (x, y),可以和小学妹一起走多少步?重复走过
的地方只算一次。
峡谷被定义为二维数组。峡谷只会出现 . 代表路;# 代表怪男爵,碰到就死亡, 在峡谷中只能向上下
左右四个方向走。

Input

第一行两个整数 N, M(1 ≤ N ≤ 1000, 1 ≤ M ≤ 1000)
接下来 N 行 M 列迷宫
然后一个 Q(1 ≤ Q ≤ 105
) 代表有 Q 次询问
接下来 Q 行,每行包含两个正整数 x, y,表示早队初始被传送到的起点

Output

输出包含 Q 行,每行输出一个整数代表早队最多可以和小学妹一起旅行多少步,如果一步都无法前
进,请输出 -1.

Examples

input:
3 3
#.#

##.
2
2 2
3 3
output:
4
4

标程

恶心了zmr整整一天的题目,不是tle就是re
对于该题,要所算出来的bfs存到一个数组里,方便直接访问,当然存的方法也有好有坏(恶心的根源)
上yzx学长的标程

#include<stdio.h>
#include<iostream>
#include<queue>
using namespace std;
int zhuanx[]={0,0,1,-1};
int zhuany[]={1,-1,0,0};
struct stmp{
	int x,y;
};
int k=1;
int n,m;
int v[1009][1009];
char a[1009][1009];
int ans[1000009];
queue<stmp>rr;
void bfs(int x,int y){
	while(!rr.empty()){
		rr.pop();
	}
	rr.push({x,y});
	v[x][y]=k;
	int sum=0;
	while(!rr.empty()){
		stmp nn=rr.front();
		rr.pop();
		int xx=nn.x;
		int yy=nn.y;
		for(int i=0;i<4;i++){
			int xxx=xx+zhuanx[i];
			int yyy=yy+zhuany[i];
			if(xxx>=0&&yyy>=0&&xxx<n&&yyy<m&&a[xxx][yyy]=='.'&&v[xxx][yyy]==0){
				sum++;
				v[xxx][yyy]=k;
				rr.push({xxx,yyy}); 
			}
		}
	}
	ans[k++]=sum;
}
int main(){
	//freopen("1.txt","w",stdout);
	scanf("%d %d",&n,&m);
	for(int i=0;i<n;i++){
		scanf("%s",a[i]); 
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			if(a[i][j]!='#'&&v[i][j]==0){
				bfs(i,j);
			} 
		}
	}
	int t;
	scanf("%d",&t);
	while(t--){
		int x,y;
		scanf("%d %d",&x,&y);
		if(a[x-1][y-1]!='#'){
			if(ans[v[x-1][y-1]]!=0){
				printf("%d\n",ans[v[x-1][y-1]]);
			}else{
				printf("-1\n");
			}
		}else{
			printf("-1\n");
		} 
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值