递归-洛谷P5461赦免战俘

一、题目洛谷P5461赦免战俘

在这里插入图片描述
在这里插入图片描述

二、解法

分析:每次都是先处理一个大的矩阵,处理大矩阵的时候是把这个矩阵按条件分为四个,左上角不处理,右上角、左下角、右下角需要做相同的处理,相同的处理就是:把这当前的矩形再分为四部分,左上角不处理,右上角、左下角、右下角需要做相同的处理……到什么时候结束呢?一直到当前的这个矩形不能再分的时候为止,什么时候不能再分呢?即边长为0 的时候。

1、怎么确定每次需要进行分割的矩阵?
每次处理的时候都要看三个矩阵,即右上角,左上角,右下角,为了区别,用矩阵左上角的坐标+边长就可以确定要处理的矩形。每一次处理三个矩形的时候,矩形的边长都是一样的,到下次处理的时候,边长要除以2。
2、画图

假设n是2,边长为4,第一次就是一个大的正方形,要处理以图中1,2,3为顶点的小矩形,注意大矩形的边长为4,3个小矩形的边长为2。

在这里插入图片描述
然而三个小矩形还要继续分割下去,就是把自己看成一个大的矩形,然后再对自己的边长除以2,于是有了第二次处理,第一次的3个小矩形的1,2, 3顶点,这次变成了对于当前矩形的顶点,这次有三个需要分隔的矩形,每个矩形都要依据3个顶点再进行分割处理,每个矩形相对应位置顶点的变化是一样的,边长要渐少一半。
在这里插入图片描述
每个黄色的矩形是要再次进行分割的矩形,但是在计算每个黄色矩形要分割的三个矩形的时候,发现要分割的矩形的边长为0,就是无法分割了,于是把当前的每个小格子置为1.

3、遍历过程
在这里插入图片描述

1、递归常规解法

#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std; 
int a[1030][1030], n;//方形数组记录每名战俘是否被豁免 
void shemian(int x, int y, int b) {//把顶点为x,y,边长为b的矩阵进行分割 
	if (b == 0) a[x][y] = 1;//如果这个格子不能再分,那这个格子的战俘无法赦免 
	else {
		shemian(x + b / 2, y, b / 2);//右上矩阵 
		shemian(x, y + b / 2, b / 2);//左下矩阵 
		shemian(x + b / 2, y + b / 2, b / 2);//右下矩阵 
	}		
}
void output(int b) {
	for (int i = 0; i < b; i++)  {
		for (int j = 0; j < b; j++) 
			cout << a[i][j] <<" ";
		cout << endl;
	}
}
int main() { 
	scanf("%d", &n);
	int bian = pow(2, n);//计算边长 
	shemian(0, 0, bian);//赦免战俘程序 
	output(bian);//输出 
	return 0;
}

2、递归解法+左移

#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std; 
int a[1030][1030], n;//方形数组记录每名战俘是否被豁免 
void shemian(int x, int y, int b) {
	if (b == 0) a[x][y] = 1;//如果这个格子不能再分,那这个格子的战俘无法赦免 
	else {
		shemian(x + (1 << b - 1), y, b - 1);//右上矩阵 
		shemian(x, y + (1 << b - 1), b - 1);//左下矩阵 
		shemian(x + (1 << b - 1), y + (1 << b - 1), b - 1);//右下矩阵 
	}		
}
void output(int b) {
	for (int i = 0; i < 1 << b; i++)  {
		for (int j = 0; j < 1 <<  b; j++) 
			cout << a[i][j] <<" ";
		cout << endl;
	}
}
int main() { 
	scanf("%d", &n);
	shemian(0, 0, n);//赦免战俘程序 
	output(n);//输出 
	return 0;
}
  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值