今天没有别的东西全是dfs,刚学嘛多搞点练一下呗
题目描述
由数字 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 30 1≤n≤30。
这题目打了搜索的标签那就用搜索来搞 ,n最大才30.不怕的啦。
思路就是把外围的0给它找到然后用另一张专门的标记地图来标记,最后再染色在原地图的上为0且未被标记的就是被围住的0把他们变成2,然后输出就可以了。(这思路绝对够易懂)
上码。
#include<stdio.h>
int a[33][33]={0};
int b[33][33]={0};
int bx[4]={0,0,1,-1};
int by[4]={1,-1,0,0};
int n;//没错这又是方向键上下左右baba
void ji(int v){
for(int p=1;p<=v;p++){
for(int y=1;y<=v;y++)
printf("%d ",b[p][y]);
printf("\n");
}
}
void f(int x,int c){
if(b[x][c]==1||x<0||c>n+1||x>n+1||c<0){
return;
}
else{
a[x][c]=1;
for(int y=0;y<4;y++){
if(b[x+bx[y]][c+by[y]]==0&&a[x+bx[y]][c+by[y]]==0){//标记了就没必要再标记了
f(x+bx[y],c+by[y]);
//没有要还原的。
}
}
}
}
void F(int n){//涂颜色的环节
for(int h=1;h<=n;h++){
for(int j=1;j<=n;j++){
if(b[h][j]==0&&a[h][j]==0)//没有被a数组标记的0那就是被围住的。
b[h][j]=2;
}
}
ji(n);
}
int main(){
scanf("%d",&n);
for(int m=1;m<=n;m++){
for(int u=1;u<=n;u++){
scanf("%d",&b[m][u]);
}
}
f(0,0);//从0,0开始你也可以从其它的最外圈的一个点开始,都可以的啦。
F(n);
return 0;
}
不过有些要注意的了,外围的0可能没连在一起 ,那就搜了个寂寞,我刚开始就错了,所以我们就给它多加一圈,这就是n+1的含义。
再来再来
由于近期的降雨,雨水汇集在农民约翰的田地不同的地方。我们用一个 N\times M(1\leq N\leq 100, 1\leq M\leq 100)N×M(1≤N≤100,1≤M≤100) 的网格图表示。每个网格中有水(W
) 或是旱地(.
)。一个网格与其周围的八个网格相连,而一组相连的网格视为一个水坑。约翰想弄清楚他的田地已经形成了多少水坑。给出约翰田地的示意图,确定当中有多少水坑。
输入第 11 行:两个空格隔开的整数:NN 和 MM。
第 22 行到第 N+1N+1 行:每行 MM 个字符,每个字符是 W
或 .
,它们表示网格图中的一排。字符之间没有空格。
输出一行,表示水坑的数量。
输入输出样例
输入 #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开始对八个方向进行搜索,采用标记染色的方法,将走过的路径标记上,每全部搜索一次ans+1
这个提示一下就给了思路没啥说的dfs就这莫写就完了,但是这个标记就有点说法了看下面的代码是如何处理的。
#include<stdio.h>
char a[102][102];
//打标记的数组
int bx[8]= {0,0,1,-1,1,1,-1,-1};
int by[8]= {1,-1,0,0,1,-1,1,-1};
int n,v;//没错这又是方向键不过方像是八个了
int i=0;
void f(int x,int c)
{
a[x][c]='.';//因为原有的数据不要输出那改了也没关系的就不开标记地图了,可以理解为填坑抓到一个填一个。
for(int y=0; y<8; y++)
{
if((x+bx[y]>=0&&x+bx[y]<n)&&(c+by[y]>=0&&c+by[y]<v))//不要越界。
{
if(a[x+bx[y]][c+by[y]]=='W') //标记了就没必要再标记了
{
f(x+bx[y],c+by[y]);//往下找W
//没有要还原的。
}
}
}
}
int main()
{
scanf("%d%d",&n,&v);//
for(int m=0; m<n; m++)
{
scanf("%s",a[m]);
}
for(int l=0; l<n; l++)
{
for(int y=0; y<v; y++)
{
if(a[l][y]=='W')
{
f(l,y);//把这个水坑全给它填了
i++;
}
}
}
printf("%d",i);
return 0;
}
ok下一个。
题目背景
kkksc03 的大学生活非常的颓废,平时根本不学习。但是,临近期末考试,他必须要开始抱佛脚,以求不挂科。
题目描述
这次期末考试,kkksc03 需要考 44 科。因此要开始刷习题集,每科都有一个习题集,分别有 s_1,s_2,s_3,s_4s1,s2,s3,s4 道题目,完成每道题目需要一些时间,可能不等(A_1,A_2,\ldots,A_{s_1}A1,A2,…,As1,B_1,B_2,\ldots,B_{s_2}B1,B2,…,Bs2,C_1,C_2,\ldots,C_{s_3}C1,C2,…,Cs3,D_1,D_2,\ldots,D_{s_4}D1,D2,…,Ds4)。
kkksc03 有一个能力,他的左右两个大脑可以同时计算 22 道不同的题目,但是仅限于同一科。因此,kkksc03 必须一科一科的复习。
由于 kkksc03 还急着去处理洛谷的 bug,因此他希望尽快把事情做完,所以他希望知道能够完成复习的最短时间。
输入格式
本题包含 55 行数据:第 11 行,为四个正整数 s_1,s_2,s_3,s_4s1,s2,s3,s4。
第 22 行,为 A_1,A_2,\ldots,A_{s_1}A1,A2,…,As1 共 s_1s1 个数,表示第一科习题集每道题目所消耗的时间。
第 33 行,为 B_1,B_2,\ldots,B_{s_2}B1,B2,…,Bs2 共 s_2s2 个数。
第 44 行,为 C_1,C_2,\ldots,C_{s_3}C1,C2,…,Cs3 共 s_3s3 个数。
第 55 行,为 D_1,D_2,\ldots,D_{s_4}D1,D2,…,Ds4 共 s_4s4 个数,意思均同上。
输出格式
输出一行,为复习完毕最短时间。
输入输出样例
输入 #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 201≤s1,s2,s3,s4≤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}\leq601≤A1,A2,…,As1,B1,B2,…,Bs2,C1,C2,…,Cs3,D1,D2,…,Ds4≤60。
我还没有学贪心算法,看题解的时候很多人用了贪心都没对,最后还是然我看到了dfs你永远可以相信dfs(当然得数据小大的请绕道看看bfs)
思路就是把情况都列举一遍,每道题目都给分别给左右脑子试试,每一条分支都会有一个结果分支返回的时候与当前的min比较一下如果还小的话就令min等于这个。把所有的分支走完就会得到最短得时间,再加到总时间里面去。
上码!
#include<stdio.h>
int a[21]={0};
int i=0;
int s[4];
int min;
int R=0,L=0;//两个脑子
void ji(int x,int b){
if(x>=s[b]){
if(min>(R>L?R:L))//比一康康是否比原来时间短
min=R>L?R:L;//是的就取这个。
return;
}
else{
R=R+a[x];
ji(x+1,b);
R=R-a[x];//还原
L=L+a[x];//方到另一个脑子康康
ji(x+1,b);
L=L-a[x];//还原拉
}
}
int main(){
int l;
scanf("%d%d%d%d",&s[0],&s[1],&s[2],&s[3]);
for(int y=0;y<4;y++){
R=0,L=0;// 给脑子初始化到了下一科了。
for(l=0;l<s[y];l++){
scanf("%d",&a[l]);
}
min=9999;//初始化,不然你的min会是上次的原值
ji(0,y);
i=i+min;
}
printf("%d",i);
return 0;
}
R=R+a[x]; ji(x+1,b); R=R-a[x];//还原 L=L+a[x];//方到另一个脑子康康 ji(x+1,b); L=L-a[x];//还原拉
这里是这代码的精华需要完全理解如果理解的话那什么了,这对你就是小菜。
报告长官 over!