您的位置:首页 > 编程语言 > C语言/C++

回溯算法的应用:C语言中的堡垒问题(不要把换行符输到数组里QAQ)

2017-11-03 16:52 274 查看
描述

城堡是一个4×4的方格,为了保卫城堡,现需要在某些格子里修建一些堡垒。城堡中的某些格子是墙,其余格子都是空格,堡垒只能建在空格里,每个堡垒都可以向上下左右四个方向射击,如果两个堡垒在同一行或同一列,且中间没有墙相隔,则两个堡垒都会把对方打掉。问对于给定的一种状态,最多能够修建几个堡垒。

输入

每个测例以一个整数n(1<=n<=4)开始,表示城堡的大小。接下来是n行字符每行n个,‘X’表示该位置是墙,‘.’表示该位置是空格。n等于0标志输入结束。

输出

每个测例在单独的一行输出一个整数:最多修建堡垒的个数。

输入样例

4

.X..

….

XX..

….

2

XX

.X

3

.X.

X.X

.X.

3



.XX

.XX

4

….

….

….

….

0

输出样例

5

1

5

2

4

这道题的输入很奇怪!!!很容易错!!!

如果用两个for循环和scanf一个个输入字符,会把换行符输入进去。

用一个for循环和gets一行一行输入,也会把第一个n后面的换行符输入进去。

所以还要在前面加一个getchar把第一个换行符存到temp变量中。

总之很坑QAQ

#include<stdio.h>
int output[100]={0};//存储结果的数组
int n;
int cnt=0;//用来记录输入了几组数据,方便存出结果和输出。
char cb[5][5];//城堡地图
int bl[5][5];//放堡垒的地图
//两个地图是重合的
void testout()//检查建了多少个堡垒,记录最大堡垒数。
{
int sum=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(bl[i][j]==1) sum++; //一共建了多少堡垒
}
}
if(sum>output[cnt]) output[cnt]=sum;//把最大堡垒数存在数组output中
}
int check(int m)//检查此处是否能建堡垒
{
int x=m/n;
int y=m%n;
if(bl[x][y]==0) return 1;//没有堡垒是一定符合要求的。直接返回1。
if(cb[x][y]=='X'&&bl[x][y]==1) return 0;//有墙的地方不能建堡垒
int flag1=1,flag2=1;
for(int j=0;j<y;j++)
{
if(bl[x][j]==1)
{
flag1=0;
for(int i=j+1;i<y;i++)
{
if(cb[x][i]=='X') flag1=1;
}
}
}
for(int j=0;j<x;j++)
{
if(bl[j][y]==1)
{
flag2=0;
for(int i=j+1;i<x;i++)
{
if(cb[i][y]=='X') flag2=1;
}
}
}
//新建的堡垒必须和同一行或同一列的其他堡垒间相隔一堵墙
if(flag1==1&&flag2==1)
{
return 1;
}
else return 0;
}
void chengbao(int m)
{
if(m==n*n)
{
testout();
}
int x=m/n;
int y=m%n;//将一维数字转换为二维数组的坐标 (从0开始)
if(m<n*n)
{
for(int i=1;i>=0;i--)
{
bl[x][y]=i;
if(check(m)==0) continue;//不符合要求则继续取值或回溯至符合要求
else chengbao(m+1); //符合要求则继续递归调用
}
}
}
void print()//输出
{
for(int i=1;i<=cnt;i++)
{
printf("%d\n",output[i]);
}
}
int main()
{
while(1)//输入数据
{
scanf("%d",&n);
if(n==0) break;
cnt++;
char temp=getchar();//把n后面的换行符存进去,否则会存入cb数组
for(int i=0;i<=n-1;i++)
{
gets(cb[i]);
}
chengbao(0);//每输入完一组数据,进行一次运算
}
print();//输出结果
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言 回溯 输入