回溯法解决火力网问题(功能完整版)

网上搜索的回溯法解决火力网问题基本上搜不出来,或者注释不明确,功能不完整。

火力网问题描述

假设我们有一个直街道广场的城市。一个城市的地图用n行n列的方形板,每一个代表一个街道或一块墙。

一个碉堡就是一个小城堡,有四个开口用以射击。四开口面朝北,东,南,西,分别。会有一个机枪射击通过每个开口。

在这里,我们假定子弹是如此强大,它可以运行在任何距离和毁灭的道路上一个碉堡。另一方面,墙是如此强烈地建成,可以阻止子弹。

其目标是把城市中的许多碉堡使没有两个可以摧毁对方。一个配置的碉堡是法律规定,没有两个碉堡是在地图上的同一行或列除非有至少一个墙壁将他们分离。

请问最多存在多少堡垒,并一一输出他们的情况。

你需要做的是规定方形城市的大小和墙壁的位置,

下图为一个可行的火力网示例

代码实现

#include <stdio.h>
int  arr[100][100]={0};//0是空白 1是路 2是墙 3为碉堡 4为边界 
int count ,n;

void makearr(int n){			//初始化数组 设置边界 和墙的位置 
	int i=0,j=0;
	for(int x= 0;x<n;x++){
		for (int y =0;y<n;y++)
		{
			arr[x][y]=1;						
		}
	}
		for(int a=0;a<n;a++){
		arr[n][a]=4;
		arr[a][n]=4;
	}
	printf("请输入墙的个数") ;
	int sum;
	scanf("%d",&sum) ;
	for(int a=1;a<=sum;a++){
		printf("请输入第%d块墙的具体行数",a);
		scanf("%d",&i);
		printf("请输入第%d块墙的具体列数",a);
		scanf("%d",&j);
		arr[i-1][j-1]=2;
	}
}
void printarr(int n){   //打印城市情况
    count++;
    printf("\n%d:\n", count);
	for(int i=0;i<n+1;i++){
		printf("\n\n");
		for (int j=0;j<n+1;j++){
			if( arr[i][j]==1){
				printf ("    ") ;
			}
			else if (arr[i][j]==2)
				printf("墙  ");
			else if (arr[i][j]==3) 
				printf("堡  "); 
			else if (arr[i][j]==4) 
				printf("*   "); 
			else if (arr[i][j]==0) 
				printf("    "); 
		}
	} 
}
int isTrue(int a, int b) 
{                     
	if(arr[a][b]!=1){
		return 0;
	}
    int t;
    for(t=a-1; t>=0; t--)     // 向上判断 
    {
        if(arr[t][b] ==2) break;
 		if(arr[t][b] ==3) return 0;
    }
    for(t=b-1; t>=0; t--){      // 向左判断
        if(arr[a][t] == 2) break;
        if(arr[a][t] == 3) return 0;
    }
    return 1;
} 
void fun(int m){
        if(m == n)  
    {
        printarr(n);    // 输出 
        return;     // 递归出口 
    }
    int i;
    for(i=0; i<n; i++)
    {
        if(isTrue(m, i))    // 回溯算法 
        {
            arr[m][i] = 3;  
            fun(m+1);      
            arr[m][i] = 1;   
        }
    }
}

int main(){
	printf("请输入边界N为多大") ;
	scanf("%d",&n);
	makearr(n);
    fun(0);
	return 0;
}

 代码中fun为主要的回溯算法,定义一个m=0;m代表地图的行,从地图的第一行开始往下遍历,如果m能够达到最后一行而且完整运行,此时m数的大小由n-1变为n,fun结束,打印并结束此次递归。

部分运行结果

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值