蛇形填数&开灯问题 精讲

蛇形填数&开灯问题 精讲

暑期集训已经开始两天了,有种被拖着跑的感觉,我感觉自己的基础太差了,有些简单的动态规划,能听懂,思路也不难,就是自己打的时候,全是bug,连深搜,广搜的算法都需要看一两天才能明白具体的内容,究其根本还是打的代码太少,所以我觉得自己还是应该从基本的编程基础开始,在刷题中,巩固境界,一点点的进步,毕竟每个人的情况不一样嘛。
蛇形填数
给定一个 n , 在 n * n 的方阵中填入 1 ,2, 3,……,n * n, 要求填成蛇形。

例如在 n = 5 时 , 如下所示:

13 14 15 16 1

12 23 24 17 2

11 22 25 18 3

10 21 20 19 4

9 8 7 6 5

思路:
设置一个二维数组, 以 x 代表行, y 代表列
填数的顺序是 下, 左, 上, 右
直到一个方向无法再填数时,再进行下一个方向的填数

#include<bits/stdc++.h>
#include<iostream>
#define max 20 //max的值不能太大,否则程序无法运行 
using namespace std;
int main()
{
	int n,x,y;
	cin >> n;
	x=0;
	y=n-1;
	int a[max][max];
	memset(a,0,sizeof(a));//及时的初始化 
	int top=0;
	top=a[x][y] = 1;//也可以赋值到这里面。 
	while(top<n*n)//不超过最大值,同时注意不要++放前面和后面的用法 
	{
		
		while(x+1<n && !a[x+1][y])  a[++x][y] = ++top;//从最外面先向下 
		while(y-1>=0 && !a[x][y-1])  a[x][--y] = ++top;//再往 左 
		while(x-1>=0 && !a[x-1][y])  a[--x][y] = ++top;//再往上 
		while(y+1<n && !a[x][y+1])  a[x][++y] = ++top;// 再往右
		//学会如何去用坐标控制方向,在bfs,dfs算法中也用的上,!a[x+1][y]表示,超过格子范围的数不存在 
	}
	for(x=0;x<n;x++)
	{
			for(y=0;y<n;y++)
		{
			printf("%3d",a[x][y]);//这样使打印的矩阵排列整齐 
		}
		cout<<endl;
	}
	
	return 0;
}

开灯问题
n盏灯,编号为1-n,第一个人把所有灯打开,第二个人按下所有编号两倍的开关(这些灯被关掉),第三个人按下所有编号三倍的开关,以此类推,一共有k个人,问最后有哪些灯开着?

输入:n和k,输出开着的灯的编号,k<=n<=1000

样例输入:

7 3

样例输出:

1 5 6 7

算法思路:

其实我们可以采用数组存储多少盏灯的状态,然后模拟接下来的人开关灯的操作,怎么模拟?比如我们设置两个循环,第一个循环是操作的人,第二个循环是对所有的灯循环,通过第二个循环中我们拿每一盏灯的序号来和第几个人操作的来进行取余运算,如果为0,则模拟开关灯操作,就是将数组的值取相反值即可。

#include
#include
#include
using namespace std;
int num[1001]; //定义一个数组,保存灯的状态0为关闭,1为打开

int main()
{

memset(num,0,sizeof(num)); //给数组初始化全部为0
int n,k;
cin>>n>>k;//代表灯的个数和人的人数
int flag = 1; //这个flag标识变量是用来判断输出是否为第一个 ,节省多出来的空格

	for(int i = 1;i<=k;i++){  			// 这两个循环是模拟开关灯操作 
		for(int j = 1;j<=n;j++){		//第一个循环是代表开关灯的倍数,第二个循环是判断开关灯状态以及修改操作 
			if(j%i == 0) num[j] = !num[j];//相当于赋值为一,注意这个循环的过程
		}
	} 
	
	for(int i = 1;i<=100;i++){
	if(num[i]){
		if(flag) flag = 0;    //这个是判断输出是否为第一个,是一个输出的技巧避免多出一个空格 
		else cout<<" ";
		cout<<i; 
	} 	
	}
	cout<<endl;
	return 0;
} 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/114910.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • modprobe命令不能用_modprobe查看已加载模块

    modprobe命令不能用_modprobe查看已加载模块modprobe命令用于智能地向内核中加载模块或者从内核中移除模块。modprobe可载入指定的个别模块,或是载入一组相依的模块。modprobe会根据depmod所产生的相依关系,决定要载入哪些模块。若在载入过程中发生错误,在modprobe会卸载整组的模块。语法modprobe(选项)(参数)选项 -a或–all:载入全部的模块; -c或–show-conf:显示所有模块的设置信息; -d或–debug:使用排错模式; -l或–li.

    2025年8月2日
    3
  • 关于G1收集器

    关于G1收集器G1(GarbageFirst)收集器是Oracle公司开发的一款主要面向服务端的拥有相对可靠的停顿预测模型的垃圾收集器。在垃圾收集器的历史上有着里程碑式的意义。与之前的收集器不同,G1不在基于固定的新生代与老年代的内存分配方式进行垃圾清理,而是使用了基于Region的内存分配的方式进行垃圾清理。这种方式使得G1在进行垃圾清理的时候不需要对整个新生代或老年代甚至整个Java堆进行垃圾清理,这样就极大的减少标记期间的停顿时间。设计思路:面向局部(单个或多个Region)收集内存布局:基于Regi

    2022年5月20日
    33
  • Linux查看进程占用端口号_windows查看进程占用端口

    Linux查看进程占用端口号_windows查看进程占用端口查看linux端口被哪个进程占用的方法:首先查看被占用的端口的进程,并查询进程id;然后根据集成id查询进程,并查看进程详情信息;最后查看进行所在目录,操作进程即可。本教程操作环境:redhatenterpriselinux6.1、DELLG3电脑。查看linux端口被哪个进程占用的方法:1、查询被占用的端口。首先是需要输入命令,查看被占用的端口的进程,netstat-tunpl|g…

    2022年7月27日
    2
  • href=&quot;javascript:void(0);&quot;与#差异

    href=&quot;javascript:void(0);&quot;与#差异

    2022年1月9日
    60
  • CAP 原理[通俗易懂]

    CAP 原理[通俗易懂]简单记录下分布式数据库的CAP原理

    2022年5月12日
    41
  • 调用谷歌翻译接口_api如何调用

    调用谷歌翻译接口_api如何调用在平时使用谷歌翻译的过程中,经常会遇到需要批量翻译大量文本的情景,这种时候需要调用谷歌翻译的API首先可以使用python库googletranspipinstallgoogletrans#使用方法fromgoogletransimportTranslatortranslator=Translator(service_urls=[‘translate.google.cn’])sour…

    2025年8月18日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号