12月27日刷题总结

# 填涂颜色

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

```plain
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
```
```plain
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$ 行,由 $0$ 和 $1$ 组成的 $n \times n$ 的方阵。

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

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

## 输出格式

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

## 样例 #1

### 样例输入 #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\%$ 的数据,$1 \le n \le 30$。

 思路:利用bfs(广度搜索)搜索围墙(1)外的所有0并赋值为-1(便于输出(输出的时候使用判断语句输出))。

注意事项;扩展一圈0作为搜索的路陉防止有遗漏的情况

例如:

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

此种情况左下角的俩个零不会被搜索到

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
//填土颜色
int a[32][32];
struct area
{
	int x;//横坐标
	int y;//纵坐标
	
}que[1024];
int main()
{
	int n,tx,ty;
	scanf("%d",&n);//n行n列
	//输入
	for(int i=2;i<=n+1;i++)
	{
		for(int j=2;j<=n+1;j++)
		{
			scanf("%d",&a[i][j]);
		}
	}
	int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//走的数组
	int head=1,tail=1;
	que[tail].x=1;
	que[tail].y=1;
	tail++;
	a[1][1]=-1;//遍历的起点设置为来过
	while(head<tail)
	{
		for(int k=0;k<4;k++)//四个方向的走法的遍历
		{
			tx=que[head].x+next[k][0];//(下一步对应的坐标)
			ty=que[head].y+next[k][1];
			if(tx<1||ty<1||tx>n+2||ty>n+2)//判断是否越界
			{
				continue;
			}
			if(a[tx][ty]==0)//不是围墙且没有来过
			{
				a[tx][ty]=-1;//把没有包围起来的零全部赋值为1
				que[tail].x=tx;//入队
				que[tail].y=ty;
				tail++;//队尾的扩充
			}
		}
		head++;//(当点全部扩展完成之后)出队
	}
	for(int i=2;i<=n+1;i++)
	{
		for(int j=2;j<=n+1;j++)
		{
			if(a[i][j]==0)//这里是被包围起来的数字0我们输出2
			printf("2 ");
			else
			if(a[i][j]==-1)//此处是没有包围起来的零我们直接输出0
			printf("0 ");
			else printf("1 ");//此处是数字1也就是围墙我们直接输出1
		}
		puts("");
	}
	
}
/*
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
0 1 0 0 1 1
1 1 1 1 0 1
*/

 

# 马的遍历

## 题目描述

有一个 $n \times m$ 的棋盘,在某个点 $(x, y)$ 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。

## 输入格式

输入只有一行四个整数,分别为 $n, m, x, y$。

## 输出格式

一个 $n \times m$ 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 $-1$)。

## 样例 #1

### 样例输入 #1

```
3 3 1 1
```

### 样例输出 #1

```
0    3    2    
3    -1   1    
2    1    4
```

## 提示

### 数据规模与约定

对于全部的测试点,保证 $1 \leq x \leq n \leq 400$,$1 \leq y \leq m \leq 400$。

 思路:和走迷宫很像,只不过走法更多样,设置好走法的数组即可(一定要检查好走法数组有没有设置好)(WA了几次检查了几次的教训)该题数据较大采用bfs进行搜索,把步数存入ans数组中,设置book数组防止重复走。会使得步数更新,而步数肯定是先录入的情况为最少步数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
struct que
{
	int x;//横坐标
	int y;//纵坐标
	int s;//步数的记录
}a[400*400+1];
int ans[401][401],book[401][401];
int main()
{
	int n,m,sx,sy,tx,ty;
	memset(ans,-1,sizeof(ans));
	int next[8][2]={{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2}};//8个方向走路的数组
	scanf("%d%d%d%d",&n,&m,&sx,&sy);//n行m列以及起点坐标
	int head=1,tail=1;
	book[sx][sy]=1;
	a[tail].x=sx,a[tail].y=sy,a[tail].s=0;
	ans[sx][sy]=0;//输出结果数组的起点设置为0;
	tail++;
	while(head<tail)//对列不为空的时候
	{
		for(int k=0;k<8;k++)
		{
			tx=a[head].x+next[k][0];//(下一步对应的坐标)
			ty=a[head].y+next[k][1];	
			if(tx<1||ty<1||tx>n||ty>m)//判断是否越界
			{
				continue;//越界则尝试下一种做法
			}
			if(book[tx][ty]==0)//该点没来过的时候
			{
				book[tx][ty]=1;//设置为来过
				a[tail].x=tx;//更新横纵坐标
				a[tail].y=ty;
				a[tail].s=a[head].s+1;//步数+1
				ans[tx][ty]=a[tail].s;//步数存入输出的·数组
				tail++;	//对位扩张
			}
		}
		head++;//出队
	}
	//遍历输出结果的数组输出其对应的步数
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			printf("%d ",ans[i][j]);
		}
		puts("");
	}
}

Lake Counting S

# [USACO10OCT]Lake Counting S

## 题面翻译

由于近期的降雨,雨水汇集在农民约翰的田地不同的地方。我们用一个 $N\times M(1\leq N\leq 100, 1\leq M\leq 100)$ 的网格图表示。每个网格中有水(`W`) 或是旱地(`.`)。一个网格与其周围的八个网格相连,而一组相连的网格视为一个水坑。约翰想弄清楚他的田地已经形成了多少水坑。给出约翰田地的示意图,确定当中有多少水坑。

输入第 $1$ 行:两个空格隔开的整数:$N$ 和 $M$。

第 $2$ 行到第 $N+1$ 行:每行 $M$ 个字符,每个字符是 `W` 或 `.`,它们表示网格图中的一排。字符之间没有空格。

输出一行,表示水坑的数量。

## 题目描述

Due to recent rains, water has pooled in various places in Farmer John's field, which is represented by a rectangle of N x M (1 <= N <= 100; 1 <= M <= 100) squares. Each square contains either water ('W') or dry land ('.'). Farmer John would like to figure out how many ponds have formed in his field. A pond is a connected set of squares with water in them, where a square is considered adjacent to all eight of its neighbors. Given a diagram of Farmer John's field, determine how many ponds he has.

## 输入格式

Line 1: Two space-separated integers: N and M \* Lines 2..N+1: M characters per line representing one row of Farmer John's field. Each character is either 'W' or '.'. The characters do not have spaces between them.

## 输出格式

Line 1: The number of ponds in Farmer John's field.

## 样例 #1

### 样例输入 #1

```
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
```

### 样例输出 #1

```
3
```

## 提示

OUTPUT DETAILS: There are three ponds: one in the upper left, one in the lower left, and one along the right side.

 思路:和马的遍历有一点类似,走法比迷宫更加多样,我们可以先对地图进行遍历,读取到w的时候进行搜索,把连在一块的w全部标记好,遍历的时候防止进入搜索,我们搜索一次即水坑数+1,话不多说看代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
char a[101][101];
int book[101][101],N,M;
void dfs(int x,int y)
{
	int tx,ty;
	book[x][y]=1;//标记该点
	int next[8][2]={{0,1},{0,-1},{1,0},{-1,0},{1,1},{-1,-1},{1,-1},{-1,1}};//8个方向的走法	
	for(int k=0;k<8;k++)
	{
		tx=x+next[k][0];
		ty=y+next[k][1];
		if(tx<1||ty<1||tx>N||ty>M)//判断是否越界
		continue;//此种走法越界了就另一种走法
		if(a[tx][ty]=='W'&&book[tx][ty]==0)
		{
			dfs(tx,ty);//再次调用进行搜索以达到水坑的w都被标记
		}
	}
}
int main()
{
	int ans=0;
	scanf("%d%d",&N,&M);//N行M列
	getchar();//不要忘记此处
	for(int i=1;i<=N;i++)
	{
		for(int j=1;j<=M;j++)
		{
			scanf("%c",&a[i][j]);
		}
		getchar();//也不要忘记此处
	}
	for(int i=1;i<=N;i++)
	{
		for(int j=1;j<=M;j++)
		{
			if(a[i][j]=='W'&&book[i][j]==0)//遇到w且没有被标记
			{
				dfs(i,j);//进行搜索,将连城一块的w全部搜索完
				ans++;//水坑+1
			}
		}
	}
	printf("%d",ans);
}
/*
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
*/

 考前临时抱佛脚

## 题目背景

kkksc03 的大学生活非常的颓废,平时根本不学习。但是,临近期末考试,他必须要开始抱佛脚,以求不挂科。

## 题目描述

这次期末考试,kkksc03 需要考 $4$ 科。因此要开始刷习题集,每科都有一个习题集,分别有 $s_1,s_2,s_3,s_4$ 道题目,完成每道题目需要一些时间,可能不等($A_1,A_2,\ldots,A_{s_1}$,$B_1,B_2,\ldots,B_{s_2}$,$C_1,C_2,\ldots,C_{s_3}$,$D_1,D_2,\ldots,D_{s_4}$)。


kkksc03 有一个能力,他的左右两个大脑可以同时计算 $2$ 道不同的题目,但是仅限于同一科。因此,kkksc03 必须一科一科的复习。


由于 kkksc03 还急着去处理洛谷的 bug,因此他希望尽快把事情做完,所以他希望知道能够完成复习的最短时间。

## 输入格式

本题包含 $5$ 行数据:第 $1$ 行,为四个正整数 $s_1,s_2,s_3,s_4$。

第 $2$ 行,为 $A_1,A_2,\ldots,A_{s_1}$ 共 $s_1$ 个数,表示第一科习题集每道题目所消耗的时间。

第 $3$ 行,为 $B_1,B_2,\ldots,B_{s_2}$ 共 $s_2$ 个数。

第 $4$ 行,为 $C_1,C_2,\ldots,C_{s_3}$ 共 $s_3$ 个数。

第 $5$ 行,为 $D_1,D_2,\ldots,D_{s_4}$ 共 $s_4$ 个数,意思均同上。

## 输出格式

输出一行,为复习完毕最短时间。

## 样例 #1

### 样例输入 #1

```
1 2 1 3        
5
4 3
6
2 4 3
```

### 样例输出 #1

```
20
```

## 提示

$1\leq s_1,s_2,s_3,s_4\leq 20$。

$1\leq A_1,A_2,\ldots,A_{s_1},B_1,B_2,\ldots,B_{s_2},C_1,C_2,\ldots,C_{s_3},D_1,D_2,\ldots,D_{s_4}\leq60$。

思路:采用贪心的思想,我们可以把题目看成0/1背包问题,习题的价值和时间是一致的,我们只要让左右脑所花时间尽量靠近即可。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int max(int x,int y)
{
	return x>y?x:y;
}
//看作求左右脑的0/1背包问题//习题的价值同时作为背包容量和物品价值、
//当左右脑的价值最接近的时候即为最优解
int main()
{
	int a[5][21]={0},dp[1205][1205],sum=0,temp,ans=0;
	for(int l=1;l<=4;l++)
	{
		scanf("%d",&a[l][0]);//体积和价值一致所以我们都存入数组a
	}
	for(int k=1;k<=4;k++)//分别对4门科目求最优解
	{
		sum=0;memset(dp,0,sizeof(dp));//初始化不要忘记了
		for(int j=1;j<=a[k][0];j++)
		{
			scanf("%d",&a[k][j]);
			sum+=a[k][j];
		}
		temp=sum/2;
		for(int i=1;i<=a[k][0];i++)//各个物品的遍历
		{
			for(int j=1;j<=temp;j++)//体积的逐渐增加
			{
				if(j<a[k][i])//该体积下不能装上这个物品
				{
					dp[i][j]=dp[i-1][j];//仍然为上个物品的价值
				}
				else //可以装上该物品的情况
				{
					dp[i][j]=max(dp[i-1][j],dp[i-1][j-a[k][i]]+a[k][i]);//选与不选选取其中大的一个
				}
			}
		}
		ans+=max(dp[a[k][0]][temp],sum-dp[a[k][0]][temp]);//ans累加大的//也可以累加另一个脑的,因为另一个闹所花时间一点大于计算的这个脑
	}
	printf("%d",ans);
}
/*
1 2 1 4	
5
4 3
1
1 2 3 7
*/
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卡卡卡卡罗特

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值