22/12/26总结

P1162 填涂颜色

题目描述

由数字 00 组成的方阵中,有一任意形状闭合圈,闭合圈由数字 11 构成,围圈时只走上下左右 44 个方向。现要求把闭合圈内的所有空间都填写成 22。例如:6\times 66×6 的方阵(n=6n=6),涂色前和涂色后的方阵如下:

0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1

输入格式

每组测试数据第一行一个整数 n(1 \le n \le 30)n(1≤n≤30)。

接下来 nn 行,由 00 和 11 组成的 n \times nn×n 的方阵。

方阵内只有一个闭合圈,圈内至少有一个 00。

//感谢黄小U饮品指出本题数据和数据格式不一样. 已修改(输入格式)

输出格式

已经填好数字 22 的完整方阵。

输入输出样例

输入 #1复制

6
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1

输出 #1复制

0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1

说明/提示

对于 100\%100% 的数据,1 \le n \le 301≤n≤30。

 刚看到这个题目的时候,一般都会想到DFS,但是我还想到一个当时感觉非常正确的解法,

就是遍历地图上每一个点,然后再遍历它的四个方向,如果四个方向都有1,那这个数就是被包围的。

#include<stdio.h>
int a[35][35], b[35][35],cnt=0,n;
int f(int x, int y)
{
	cnt = 0;
	int i, j;
	i = x;
	j = y;
	while (j < n)
	{
		if (a[i][++j] == 1)//记得一定不用把该点判断进去,即要++j而不是j++。否则如果该点是1,那四个方向cnt++。
		{
			cnt++;
			break;
		}
	}
	i = x;
	j = y;
	while (j>0)
	{
		if (a[i][--j] == 1)
		{
			cnt++;
			break;
		}
	}i = x;
	j = y;
	while (i< n)
	{
		if (a[++i][j] == 1)
		{
			cnt++;
			break;
		}
	}i = x;
	j = y;
	while (i> 0)
	{
		if (a[--i][j] == 1)
		{
			cnt++;
			break;
		}
	}

	return cnt;
}

int main()
{
	scanf_s("%d", &n);
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			scanf_s("%d", &a[i][j]);

	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			if (f(i, j)==4&&a[i][j]!=1)//f()==4代表该点被包围
			{
				a[i][j] = 2;
			}

	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
			printf("%d ", a[i][j]);
		printf("\n");
	}

	return 0;

}

后来在洛谷上只通过了5个例,其实这个代码有很大缺陷,比如当1围成G的形状时,也会算成被包围,显然是错误的。

应该有优化的可能性,不过暂时想不出了,所以还是老老实实用DFS吧。

思路很简单,先把不是1的都赋值2,再通过对第一个点的DFS,将包围圈外面的赋值0;

DFS也要注意,如果只是从地图的第一个点开始DFS,如果第一个点就是1,可能就会把被包围的当成包围圈外面的。所以要在地图外面加一圈。

//涂色
//首先在所给地图的外面加上一圈,可以避免一些错误,比如1在地图边界处
#include<stdio.h>
struct note {
	int x;
	int y;
};
int n,tx,ty, a[35][35], book[35][35];
int main()
{
	struct note que[1000];
	int n, a[35][35];
	int next[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		{
			scanf("%d", &a[i][j]);
			if(a[i][j]==0)
				a[i][j] = 2;//先把大地图不是1的地方赋值2;后面用dfs把在包围外面的变成0即可


		}

	for (int i = 0; i <= n + 1; i++)
	{
		a[0][i] = 2;
		a[n + 1][i] = 2;
	}
	for (int i = 0; i <= n + 1; i++)
	{
		a[i][0] = 2;
		a[i][n + 1] = 2;
	}
		int head, tail;
	head = 0;
	tail = 0;//0还是1?
	que[tail].x = 0;
	que[tail].y = 0;
	book[0][0] = 1;
	tail++;

	while (head < tail)//队列不为空时循环
	{
		for (int k = 0; k <= 3; k++)
		{
			tx = que[head].x + next[k][0];
			ty = que[head].y + next[k][1];

			if (tx<0 || tx>n+1 || ty<0 || ty>n+1)
				continue;

			if (a[tx][ty] == 2 && book[tx][ty] == 0)
			{
				book[tx][ty] = 1;
				a[tx][ty] = 0;
				que[tail].x = tx;
				que[tail].y = ty;
				tail++;
			}
		}
		head++;
	}


	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
			printf("%d ", a[i][j]);
		printf("\n");
	}
	return 0;
}

Fooldfill漫水填充法//需要使用深度优先搜索

#include<stdio.h>
int n, m, a[25][25],book[25][25];
void dfs(int x, int y, int color)
{
	int next[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };//四个方向
	int tx, ty;
	for (int k = 0; k <= 3; k++)
	{
		tx = x + next[k][0];
		ty = y + next[k][1];

		if (tx<1 || tx>n || ty<1 || ty>m)
			continue;

		if (a[tx][ty] > 0&&book[tx][ty] == 0)
		{
			a[tx][ty] = color;
			book[tx][ty] = 1;
			dfs(tx, ty, color);


		}
	}
	return;
}

int main()
{
	int num = 0;
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			scanf("%d", &a[i][j]);

	//对每个大于0的点尝试进行dfs染色
	
	for(int i=1;i<=n;i++)
		for (int j = 1; j <= m; j++)
		{
			if (a[i][j] > 0)
			{
				num--;
				book[i][j] = 1;//容易忽略
				a[i][j] = num;//对每片区域的第一个数也要染色
				dfs(i, j, num);
				
			}
		}

	//输出染色后的地图
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
			printf("%3d", a[i][j]);
		printf("\n");
	}

	printf("有%d个小岛", -num);

	return 0;

}

图的遍历
深度优先搜索遍历邻接矩阵
输入邻接矩阵的长和宽,再告诉你图中顶点的边,要求输出图,(输出按照被深度优先搜索遍历到的顺序)

//需要我们做以下几件事
1  将图以邻接矩阵的形式储存下来,顶点1和顶点2有边,就是e[1][2]=1,因为是无向图,所以还有e[2][1]=1。没有边就是e[2][1]=99999999,顶点与自身是e[2][2]=0;
2  定义一个深搜函数dfs,参数只有一个,表示当前遍历到的顶点,函数递归结束的条件是sum==n,其中sum表示目前遍历完的顶点的个数,n是顶点个数。如果没有达到结束条件,  遍历邻接矩阵,判断当前顶点与顶点i是否有边,顶点i是否已经访问过


#include<stdio.h>
int book[101], sum, n, e[101][101];
void dfs(int cur)
{
	printf("%d ", cur);//遍历到哪个顶点就输出哪个顶点
	//遍历完一个顶点就sum++
	sum++;
	if (sum == n) return;
	

	//如果顶点还没有被遍历完

	for (int i = 1; i <= n; i++)
	{
		if (e[cur][i] == 1 && book[i] == 0)
		{
			book[i] = 1;
			dfs(i);
		}
	}
	return;

}
int main()
{
	int m, a, b;
	scanf_s("%d %d", &n, &m);//这里n表示的是正方形邻接矩阵的边长,m表示的是输入的顶点的边的数量,m=3就输入3对,m=5就输入5对
 for(int i=1;i<=n;i++)
    for (int j = 1; j <= n; j++)
{
	if (i == j)e[i][j] = 0;
	e[i][j] = 99999999;
}
	for (int i = 1; i <= m; i++)
	{
		scanf_s("%d %d", &a, &b);
		e[a][b] = 1;
		e[b][a] = 1;
	}

	book[1] = 1;
	dfs(1);

	return 0;
}

问题 H: 密码锁问题(JSU-ZJJ内存限制:64 MB时间限制:5.000 S

内存限制:64 MB时间限制:5.000 S

评测方式:文本比较命题人:外部导入

提交:365解决:279

返回比赛提交提交记录

题目描述

一个微调密码锁是这样的一种锁,这种锁你仅能转动密码盘。这是一种常见的密码盘,通过仅在允许的组中改变这些密码盘以微调某个值。
设想一行有D个编号的密码盘,每个密码盘顺序有0到9共九个数字。这类似于密码箱的组合锁。
下面是一系列B按钮,每个按钮标记有D位数字。例如,D可能是4标记就是1000 1200 1002 0111.按标记为1000的按钮,则仅转动第一个转盘一次,而其他转盘不动,而按按钮1002则转第一个转盘一次,转第四个转盘两次,剩下的不动。每个盘按循环的方式转动,即如果转到9,再转一次,就又转回0.
你的任务是模仿这样一个上锁的微调密码锁,给出最终的各密码盘的读数。

输入

输入的每个测试数据的第一行包含有D个数字(至多10个),表示密码盘的起始位置。接下来的每一行有一排有标记的按钮,表示下一次会按的按钮。

输出

对每个测试用例用一行输出最终各密码盘的读数。

样例输入 复制

0001
1003
0206
0034
1111
1003

样例输出 复制

3348

 思路其实很简单,先通过第一行数据得出密码的长度并将该串字符的每一位的值-‘0’(字符‘6’的阿斯伽马值减去’0‘的阿斯伽马值得到数字6),然后多组输入,每输入一串字符,就将该串字符的每一位的值-‘0’(字符‘6’的阿斯伽马值减去’0‘的阿斯伽马值得到数字6),累加到对应的c[i]里,最后输出的时候用a[i]%10就可以了。

#include<stdio.h>
#include<string.h>
int c[15];
int main()
{
	int i = 0,n;
	char a[100];
	char b[100];
	
  
	gets(a);

	n = strlen(a);
	for (int i = 0; i < n; i++)
		c[i] += a[i]-'0';//字符‘6’的阿斯伽马值减去’0‘的阿斯伽马值得到数字6
	while (gets(b) != NULL)
	{
		for (int i = 0; i < n; i++)
			c[i] += b[i]-'0';

	}

	for (int i = 0; i < n; i++)
		printf("%d", c[i] % 10);//一共10个数字,对10取余即可

	return 0;

}

问题 F: 数数字

内存限制:128 MB时间限制:1.000 S

评测方式:文本比较命题人:20154206121

提交:4385解决:1185

返回比赛提交提交记录

题目描述

问题很简单有个1到n的数列,数一下其中能够被2,3,5整除的数字的个数。例如当n = 6 ,的时候有 2,3,4,5 , 6.这5个数满足条件,所以我们应该输出5,是不是很简单?

输入

多组输入到文件尾,每组输入一个n (n < 1e9 )

输出

输出对应的个数

样例输入 复制

1
2
6

样例输出 复制

0
1
5

一开始没注意时间限制,写上去一提交发现事情不对劲,然后想用数组把能被整除的记录下来,后来发现这样很蠢,一是这样并不能节约时间,二是没有这么大的数组。

后来在csdn上看到另外一个题目的题解,说的是n/6的值就是从1到n内能被6整除的数的个数。比如100/3=33.3,那么从1到100内就有33个数能被3整除。后来想想其实特别好理解,就是100能被3分成33.3份,我从3开始,每次加3,能加32次,加上一开始的3就是33个数,每次加的都是3肯定能被3整除。

但是这还不够,因为1到6满足条件的有3+2+1=6种,但答案却是5,其实是因为6既能被2整除又能被3整除。于是在百度上发现了下面这个容斥定理:

A类和B类和C类元素个数总和= A类元素个数+ B类元素个数+C类元素个数—既是A类又是B类的元素个数—既是A类又是C类的元素个数—既是B类又是C类的元素个数+既是A类又是B类而且是C类的元素个数。(A∪B∪C = A+B+C - A∩B - B∩C - C∩A + A∩B∩C)

这时事情就变得简单起来了,代码如下:

#include<stdio.h>
int main()
{
	int n;
	int cnt = 0;
	while (~scanf("%d", &n))
	{
		cnt = n / 2 + n / 5 + n /3;
		cnt = cnt - n / 6 - n / 10 - n / 15 + n / 30;
		//n/6是既能被2整除又能被3整除的
        //n/10是既能被2整除又能被5整除的
        //n/15是既能被3整除又能被5整除的
       //n/30是既能被2整除又能被3整除还能被5整除的
		printf("%d", cnt);
	}

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript数组有很多内置方法,可以操作和处理数据。以下是JavaScript数组的所有方法列表: 1. `concat()` - 连接两个或多个数组。 2. `copyWithin()` - 在数组内部将一段元素拷贝到另一个位置。 3. `entries()` - 返回一个迭代器对象,可以遍历数组所有的键值对。 4. `every()` - 检查数组中的所有元素是否满足一个条件。 5. `fill()` - 用静态值填充一个数组中的所有元素。 6. `filter()` - 通过指定条件过滤出符合条件的数组元素。 7. `find()` - 返回找到的第一个元素,满足条件。 8. `findIndex()` - 返回目标元素索引,满足条件。 9. `forEach()` - 遍历数组,对每个元素执行指定的操作。 10. `includes()` - 判断数组是否包含指定元素。 11. `indexOf()` - 返回指定元素第一个出现的位置索引。 12. `join()` - 连接数组元素,返回字符串。 13. `keys()` - 返回一个迭代器对象,可以遍历数组的键。 14. `lastIndexOf()` - 返回指定元素最后一次出现的位置索引。 15. `map()` - 遍历数组,对每个元素执行指定的操作,将结果放入新数组。 16. `pop()` - 删除数组最后一个元素。 17. `push()` - 在数组末尾添加一个或多个元素。 18. `reduce()` - 对数组中的每个元素执行指定的操作,累积计算并返回最终结果。 19. `reduceRight()` - 与reduce()方法类似,不过是从右到左遍历数组。 20. `reverse()` - 反转数组元素的顺序。 21. `shift()` - 删除数组的第一个元素。 22. `slice()` - 截取数组元素,返回新数组。 23. `some()` - 检查数组中是否存在至少一个元素满足一个条件。 24. `sort()` - 排序数组元素。 25. `splice()` - 删除、插入或替换数组中的元素。 26. `toString()` - 将数组转换成字符串。 27. `unshift()` - 在数组的开头添加一个或多个元素。 28. `valueOf()` - 返回数组本身。 以上方法中,有些方法会改变原数组,有些方法则不会。需要注意使用时,避免产生错误。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值