第一题:
7-1 输出全排列
分数 300
全屏浏览题目
切换布局
作者 DS课程组
单位 浙江大学
请编写程序输出前n个正整数的全排列(n<10),并通过9个测试用例(即n从1到9)观察n逐步增大时程序的运行时间。
输入格式:
输入给出正整数n(<10)。
输出格式:
输出1到n的全排列。每种排列占一行,数字间无空格。排列的输出顺序为字典序,即序列a1,a2,⋯,an排在序列b1,b2,⋯,bn之前,如果存在k使得a1=b1,⋯,ak=bk 并且 ak+1<bk+1。
输入样例:
3
输出样例:
123 132 213 231 312 321
最速AC代码:next_permutation(str.begin(),str.end())
do{
//cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<" "<<a[3]<<endl;
for(int i=0;i<4;i++)
cout<<a[i]<<" ";
cout<<endl;
}while(next_permutation(a,a+4));
也可以用最基础的DFS深度搜索
设置book【n】
AC代码:
#include<bits/stdc++.h> using namespace std; int n; int book[11],a[11]={0}; void dfs(int bushu) { if(bushu==n+1) { for(int i=1;i<=n;i++) cout<<a[i]; cout<<endl;return;} for(int i=1;i<=n;i++) { if(book[i]==0) { a[bushu]=i; book[i]=1; dfs(bushu+1); book[i]=0;} } return; } int main() { cin>>n; dfs(1); }
第二题 山
7-2 山
分数 300
全屏浏览题目
切换布局
作者 Drizzle
单位 山东科技大学
Drizzle 前往山地统计大山的数目,现在收到这片区域的地图,地图中用
0(平地)
和1(山峰)
绘制而成,请你帮忙计算其中的大山数目
山总是被平地四面包围着,每一座山只能在水平或垂直方向上连接相邻的山峰而形成。一座山峰四面被平地包围,这个山峰也算一个大山
另外,你可以假设地图的四面都被平地包围着。要求:
输入:第一行输入M,N分别表示地图的行列,接下来M行每行输入N个数字表示地图
输出:输出一个整数表示大山的数目示例:
输入:
4 5 1 1 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 1 1
输出:
3
范围:
对于 5% 的数据:M,N ≤ 10
对于 100% 的数据:M,N ≤ 2000代码长度限制
16 KB
Python (python3)
时间限制
5000 ms
内存限制
64 MB
Java (javac)
时间限制
2000 ms
内存限制
256 MB
其他编译器
时间限制
1000 ms
内存限制
256 MB
思路:使用DFS 先制图
再用for循环读图
若某点是1
则先将ans++
再向其上下左右拓展,若是1
则继续拓展
直到结束
则找到 了一个山的全部部分。
AC:
#include<bits/stdc++.h>
using namespace std;
int m,n,total;
int shan[2002][2002]={0};
int check(int x,int y)
{
if(x>n||y>m||x<1||y<1||shan[x][y]==0)
return 0;
shan[x][y]=0;
check(x+1,y);
check(x,y+1);
check(x-1,y);
check(x,y-1);
return 1;
}
int main()
{
cin>>m>>n;
for(int i=1;i<=m;i++)
{
for(int k=1;k<=m;k++)
{
cin>>shan[i][k];
}
}
for(int i=1;i<=m;i++)
{
for(int k=1;k<=m;k++)
{
if(check(i,k))
total++;
}
}
cout<<total;
}
第三题
7-3 跳跃
分数 300
全屏浏览题目
切换布局
作者 Drizzle
单位 山东科技大学
Drizzle 被困到一条充满数字的方块路中,假设这条路由一个非负的整数数组
m
组成,Drizzle 最开始的位置在下标start
处,当他位于下标i
位置时可以向前或者向后跳跃m[i]
步数,已知元素值为0
处的位置是出口,且只能通过出口出去,不可能数组越界,请你通过编程计算出Drizzle能否逃出这里。要求:
输入:第一行输入数组
m
的长度n
第二行输入数组元素,空格分割开 第三行输入起始下标start
示例:
输入:
7 4 2 3 0 3 1 2 5
输出:
True
范围:
- 1 <= m.length <= 5 * 10^4
- 0 <= m[i] < m.length
- 0 <= start < m.length
思路:还是DFS
并用book【】记录
如果落点已经在book中被记录一次
则陷入循环
无法走出 return
如果dfs找到出口
则输出True并 exit(0)
AC代码:
#include<bits/stdc++.h>
using namespace std;
int len,total,st,key=1;
int lu[50002];int book[50002]={0};
void check(int x)
{
if(lu[x]==0&&x>=0&&x<len)
{
cout<<"True";
key=0;exit(0);
}
if(x<0||x>len-1||book[x]==1)
return;
book[x]=1;
check(x+lu[x]);
check(x-lu[x]);
}
int main()
{
cin>>len;
for(int i=0;i<len;i++)
{
cin>>lu[i];
}
cin>>st;
check(st);
if(key==1)
cout<<"False";
}
第四题:
7-4 最长光路
分数 300
全屏浏览题目
切换布局
作者 neuqAcmClub
单位 东北大学秦皇岛分校
小明在做丁达尔效应的实验。
他用胶体填满了一个有 N 行, M 列个格子的透明盒子。同时,为了使实验效果更好,他在盒子的某些格子中装入一些双面镜(用“/”和“\”表示)。
当光线找到双面镜的时候,光路会反射,方向会有90度的转换(如下图所示)。
小明在填充胶体的时候产生了失误,使得有些格子光线无法穿过(我们可以认为这些格子把光线都吸收了),这些格子用大写字母“C”来表示。
现在,小明已经制作好了实验装置,他将激光光源放在第sx行的第sy个格子上。激光光源可以朝向上下左右四个方向,分别用URDL四个字母表示(“U”-上, “R”-右, “D”-下, “L”-左)。
为了让实验效果更好,小明希望光的光路越酷越好。
对小明来说,最酷的光路就是包含环的光路,这种情况下,光不会射向盒子外面,而是一直在盒子内循环(数据保证光源处的点是光线可以通过,即起点一点是".")。
如果光源朝各个方向摆设,最终光线都会射向盒子外部,那么小明认为经过格子最多的光路是最酷的。现在小明想知道光源朝哪个方向放置光路最酷。
如果光路是不包含环的,那么他还想知道光路经过的格子数目是多少(如果光多次进入同一格子,独立计算,不认为只经过一个格子)。注意
如果有多个方向是最优解,那么我们按照“U”-上, “R”-右, “D”-下, “L”-左的优先级来选择最终的答案,即如果向左和向右都是最优解,我们选择向右的方案。
同时,温馨提醒,c++中“\”符号可以用'\\'来表示
输入格式:
第一行两个数 N,M(1≤N,M≤500) 表示有N 行 M 列的格子。
接下来 N 行, 每行 M 个字符,表示盒子的具体情况。 “/”和“\”表示装有不同朝向的镜子的格子。“C”表示光线无法通过的格子。“.”表示正常且没有镜子的格子。
最后输入两个数字sx,sy表示光源所在的点。输出格式:
第一行输出一个大写字母,表示最酷的光路应该超哪个方向摆放。
第二行输出光路经过的格子数。如果光路中包含环,则换成输出字符串“COOL”。输入样例1:
5 5 ../.\ ..... .C... ...C. \.../ 3 3
输出样例1:
U 17
输入样例2:
5 7 /.....\ ../..\. \...../ /.....\ \.\.../ 3 3
输出样例2
R COOL
样例解释
S为起点 ../.\ ..... .CS.. ...C. \.../ 'U' 方向 *.*** *.*.* *C*.* *..C* ***** 17个格子 'R'方向 ../.\ ..... .C*** ...C. \.../ 3个格子 'D'方向 ../.\ ..... .C*.. ..*C. \.*./ 3个格子 'L'方向 ../.\ ..... .C*.. ...C. \.../ 1个格子
思路
感觉本题不是DFS和BFS
而是模拟
因为起点,镜子和光路图是一开始就规定好的
模拟难以实现的就是代码
本题需要注意的点是
因为入射方向不同
因此需要使用三位数组建立book
从而确定是否实现循环
AC代码
#include<bits/stdc++.h> using namespace std; int fangxiang1[4]={0,0,1,-1}; int fangxiang2[4]={1,-1,0,0}; char dirt[4]={'U','R','D','L'}; bool flag=false; char dian[505][505]; int n,m; int ans=0; int sx,sy; int final[4]={}; int temppp,step; int hanshu(char c) { if(c=='U') return 3; if(c=='D') return 2; if(c=='L') return 1; if(c=='R') return 0; return 0; } void jixu(char dir,int nx,int ny,char chushi) { if(dian[nx][ny]=='C' || nx>n || nx<1 || ny>m || ny<1) { return ; } if(dian[nx][ny]=='/') { ans++; if(dir=='L') jixu('D',nx+1,ny,chushi); if(dir=='R') jixu('U',nx-1,ny,chushi); if(dir=='U') jixu('R',nx,ny+1,chushi); if(dir=='D') jixu('L',nx,ny-1,chushi); return ; } if(dian[nx][ny]=='\\') { ans++; if(dir=='L') jixu('U',nx-1,ny,chushi); if(dir=='R') jixu('D',nx+1,ny,chushi); if(dir=='U') jixu('L',nx,ny-1,chushi); if(dir=='D') jixu('R',nx,ny+1,chushi); return ; } if(dir==chushi && nx==sx && ny==sy && ans>0) { flag=true; cout<<dir<<endl; cout<<"COOL"<<endl; exit(0) ; } temppp=hanshu(dir); step=1; while(dian[nx+fangxiang1[temppp]*step][ny+fangxiang2[temppp]*step]=='.'&& nx+fangxiang1[temppp]*step!=sx && ny+fangxiang2[temppp]*step!=sy) step++; ans+=step; jixu(dir,fangxiang1[temppp]*step+nx,fangxiang2[temppp]*step+ny,chushi); } int main() { cin>>n>>m; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { cin>>dian[i][j]; } } cin>>sx>>sy; for(int i=1;i<=4;i++) { if(flag==true) break; ans=0; jixu(dirt[i-1],sx,sy,dirt[i-1]); if(flag==false) { final[i-1]=ans; } } int *p=max_element(final,final+4); int answe=p-final; cout<<dirt[answe]<<endl; cout<<final[answe]<<endl; return 0; }
第五题 回文数列
思路,才开始的时候直接爆搜
超时QAQ
后来查看了题解才发现由于是九位数的回文数
判断是否是回文数不如直接构造回文数
再判断是否在范围内
因此:
先确定前五位(通过穷举)
再构造出九位回文数
最后再比较是否再范围内
代码;
#include<bits/stdc++.h>
using namespace std;
int shu,ans=0;
void check(int temp)
{
if(temp<=shu)
ans++;
}
int main()
{cin>>shu;
for(int n=1;n<=9;n++)
{
for(int e=0;e<=9;e++)
{
for(int s=0;s<=9;s++)
{
for(int si=0;si<=9;si++)
{
for(int f=0;f<=9;f++)
{
int temp;
temp=n*100000000+e*10000000+s*1000000+si*100000+f*10000+si*1000+s*100+e*10+n;
check (temp);
}
}
}
}
}
cout<<ans<<endl;
}