# 填涂颜色
由数字 $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
*/