双周赛2
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
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int a[10];
for(int i=1;i<=n;i++){
a[i]=i;
}
do{
for(int i=1;i<=n;i++)
{
printf("%d",a[i]);
}
puts("");
}while(next_permutation(a+1,a+1+n));
}
next_permutation()函数的使用
特有的do while结构 字典序输出全排列
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
#include<bits/stdc++.h>
using namespace std;
int a[2010][2010];int cnt;int mark[2010][2010];
void dfs(int x,int y)
{
if(a[x][y])
{
if(a[x+1][y] and mark[x+1][y]==0)
{
if(!mark[x+1][y])
{
mark[x+1][y]=1;
dfs(x+1,y);
}
}
if(a[x-1][y] and mark[x-1][y]==0)
{
if(!mark[x-1][y])
{
mark[x-1][y]=1;
dfs(x-1,y);
}
}
if(a[x][y-1] and mark[x][y-1]==0)
{
if(!mark[x][y-1])
{
mark[x][y-1]=1;
dfs(x,y-1);
}
}
if(a[x][y+1] and mark[x][y+1]==0)
{
if(!mark[x][y+1])
{
mark[x][y+1]=1;
dfs(x,y+1);
}
}
}
else
return;
}
int main()
{
int m,n;
cin>>m>>n;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
}
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(a[i][j] and mark[i][j]==0)
{
dfs(i,j);
cnt++;
}
}
}
cout<<cnt;
}
经典dfs
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
#include<bits/stdc++.h>
using namespace std;
int a[100000];int st;bool jg;int n;int po;int vis[100000];
queue<int>Q;
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
cin>>st;
Q.push(st);
vis[st]=1;
while(po<=100)
{
int frt=Q.front();
Q.pop();
int x=frt-a[frt];
if(x>=0 and x<=n-1)
{
Q.push(x);
}
int y=frt+a[frt];
if(y>=0 and y<=n-1)
{
Q.push(y);
}
if(a[frt]==0)
{
jg=1;
break;
}
po++;
}
if(jg)
cout<<"True";
else
cout<<"False";
}
bfs卡了很久
把循环数降到100就过了(虽然可能不太精确
原来是爆栈了(万恶的段错误(明明是re却报段错误。。害人不浅的pta
所以也可以剪枝 也就是去除一些不必要的搜索
设置一个数组标记搜过的点 搜过就不重复搜了
7-5 回文数文回
分数 300
全屏浏览题目
切换布局
作者 neuqAcmClub
单位 东北大学秦皇岛分校
我们称一个数是回文的,当且仅当它正着读和倒着读是相同的。
例如11或11455411是回文的,而10或1919810不是回文的。
现在给定一个数n,你需要求出区间[108,n]中所有的回文数。
输入格式:
一行一个整数n(108≤n<109)
输出格式:
输出一行一个数,表示题目所求区间中回文数的数量。
输入样例:
在这里给出一组输入。例如:
100000001
输出样例:
在这里给出相应的输出。例如:
1
思路是枚举回文数 看似很多实则是对称组成
从构成出发 枚举前半部分 八位数就简化到9*10*10*10种可能 而不用一个一个判断