8:40~11:40
第一题:
P1605
题目背景
给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
题目描述
无
输入格式
第一行N、M和T,N为行,M为列,T为障碍总数。第二行起点坐标SX,SY,终点坐标FX,FY。接下来T行,每行为障碍点的坐标。
输出格式
给定起点坐标和终点坐标,问每个方格最多经过1次,从起点坐标到终点坐标的方案总数。
输入输出样例
输入 #1复制
2 2 1 1 1 2 2 1 2
输出 #1复制
1
说明/提示
【数据规模】
1≤N,M≤5
解题思路:直接使用dfs对每一种路径进行判断,若是能走到终点计数即可。注:一种方案走完了一定要回溯。
代码如下:
#include<stdio.h>
int n,m,t;
int sx,sy,fx,fy;
int a[100],b[100];
int vis[10][10]= {0};
int sum=0;
int dx[4]= {1,-1,0,0};
int dy[4]= {0,0,1,-1};
void dfs(int x,int y)
{
if(x==fx&&y==fy)
{sum++; return;}//走到终点就计数
vis[x][y]=1;//当前这个位置极为1,表示经过了这个点
for(int i=0; i<4; i++)//往上下左右四个方向走
{
int nx=x+dx[i];//下一步经过的点
int ny=y+dy[i];
if(nx>n||nx<1||ny>m||ny<1||vis[nx][ny]==1)//若走出地图或者有障碍物或者走过的地方就不搜索
continue;
dfs(nx,ny);
vis[nx][ny]=0;//回溯
}
}
int main()
{
scanf("%d%d%d",&n,&m,&t);
scanf("%d%d%d%d",&sx,&sy,&fx,&fy);
for(int i=0; i<t; i++)
{
scanf("%d%d",a+i,b+i);
vis[a[i]][b[i]]=1;//有障碍的地方记为1
}
dfs(sx,sy);
printf("%d",sum);
}
第二题:
P2392
题目背景
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≤s1,s2,s3,s4≤20。
1≤A1,A2,…,As1,B1,B2,…,Bs2,C1,C2,…,Cs3,D1,D2,…,Ds4≤60。
解题思路:直接用dfs暴力破解然后回溯求出每门科目的最少时间然后相加。
解题代码:
#include<bits/stdc++.h>
using namespace std;
int s[5];
int a[5][25];
int i,j;
int Left,Right;
int sum=0;
int mini;
void dfs(int x)//深度搜索暴力求出最少时间
{
if(x>s[i])//次数大于这门课的题目时求出所用时间
{
mini=min(mini,max(Left,Right));//mini存最少时间
return;
}
Left+=a[i][x-1];//使用左脑所用时间
dfs(x+1);
Left-=a[i][x-1];//回溯
Right+=a[i][x-1];//使用右脑所用时间
dfs(x+1);
Right-=a[i][x-1];//回溯
}
int main()
{
for(i=0; i<4; i++)
scanf("%d",s+i);
for(i=0; i<4; i++)
{
mini=100000;//mini赋值为100000防止第一次赋值出错
Left=Right=0;
for(j=0; j<s[i]; j++)
scanf("%d",a[i]+j);
dfs(1);
sum+=mini;//时间累加入sum
}
printf("%d",sum);
return 0;
}
13.30~15.30
听英语听力40分钟。
b站学习dfs算法1小时左右。
复习数学1小时左右。
16:30~18:00
继续做题ac了一个
第三题:
P1596
题目描述
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.
由于近期的降雨,雨水汇集在农民约翰的田地不同的地方。我们用一个NxM(1<=N<=100;1<=M<=100)网格图表示。每个网格中有水('W') 或是旱地('.')。一个网格与其周围的八个网格相连,而一组相连的网格视为一个水坑。约翰想弄清楚他的田地已经形成了多少水坑。给出约翰田地的示意图,确定当中有多少水坑。
输入格式
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.
第1行:两个空格隔开的整数:N 和 M 第2行到第N+1行:每行M个字符,每个字符是'W'或'.',它们表示网格图中的一排。字符之间没有空格。
输出格式
Line 1: The number of ponds in Farmer John's field.
一行:水坑的数量
输入输出样例
输入 #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.
解题思路:暴力dfs遇到'W'就计数一次,然后dfs,把水周围8个方向全部找一遍,遇到‘W’就把'W'变为‘.’,直到把这一摊水全部搜索完。注:输入格式调试了十多分钟,用%s输入也出现了错误,最后用cin解决了。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int max_n=110;
char mp[max_n][max_n];
int n,m;
bool vis[max_n][max_n]= {0};
int dx[10]={-1,-1,-1,0,0,0,1,1,1};//x的方向
int dy[10]={-1,0,1,-1,0,1,-1,0,1};//y的方向
void dfs(int x,int y)
{
if(mp[x][y]=='W')
{
mp[x][y]='.';
for(int i=0;i<9;i++)//向8个方向继续搜索
dfs(x+dx[i],y+dy[i]);
}
}
int main()
{
int sum=0;
scanf("%d%d",&n,&m);
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
cin>>mp[i][j];//用cin解决输入格式问题
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
{
if(mp[i][j]=='W')
{
sum++;//遇到了水就直接计数
dfs(i,j);//通过dfs函数将i j周围的水全部记为旱地
}
}
printf("%d",sum);
}
20:00~20:40
继续想八皇后那题,感觉可以先打表将不可能达到要求的先剔除,但是暂时无法代码实现。
附上昨天学习总结,A掉了一个题目,一个题目有一个样例没过。
第一题:
P2404
题目描述
任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和。现在给你一个自然数n,要求你求出n的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。
输入格式
输入:待拆分的自然数n。
输出格式
输出:若干数的加法式子。
输入输出样例
输入 #1复制
7
输出 #1复制
1+1+1+1+1+1+1 1+1+1+1+1+2 1+1+1+1+3 1+1+1+2+2 1+1+1+4 1+1+2+3 1+1+5 1+2+2+2 1+2+4 1+3+3 1+6 2+2+3 2+5 3+4
说明/提示
用回溯做。。。。
n\le 8n≤8
解题思路:从1开始进行dfs,然后回溯。注:不要输出n。
AC代码如下:
#include<stdio.h>
int n;
int sum;//sum为每次减去当前数字后的和
int x[15]={1};//最小的自然数为1
void print(int a)//打印此方案
{
int i;
for(i=1;i<a;i++)
printf("%d+",x[i]);
printf("%d\n",x[a]);
}
void dfs(int a)
{
for(int i=x[a-1];i<=sum;i++)//i从上一次排列的数字开始搜索
{
if(i==n) continue;//防止输出n这个数字
sum-=i;//减去当前这个数字
x[a]=i;//将这个数字存入x数组
if(sum==0) print(a);//当sum为0的时候,证明x数组里面已经存好本次排列 输出即可
else dfs(a+1);//继续搜索
sum+=i;//上一方案已经结束,回溯进行下一排列
}
}
int main()
{
scanf("%d",&n);
sum=n;
dfs(1);
return 0;
}