棋盘问题
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放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");
}
}
}