ps:为讲解详细生动,个别注释参考了大佬的博客。
送分了QAQ
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
杭州人称傻乎乎的人为62,而嘟嘟家这里没有这样的习俗。
相比62,他那里的人更加讨厌数字38,当然啦,还有4这个
数字!所以啊,嘟嘟不点都不想见到包含38或者4的数字。
每次给出一个区间[n,m],你能找到所有令人讨厌的数字吗?
输入描述:
多组输入输出; 输入的都是整数对n、m(0如果遇到都是0的整数对,则输入结束。
输出描述:
对于每次的输入 输出全部令人讨厌的数的个数
示例1
输入
1 100
0 0
输出
20
#include<bits/stdc++.h>
const int N = 1e6 + 10;
using namespace std;
int a[N];
int judge(int n){
while(n){
if(n % 10 == 4||n % 100 == 38)
return 1;
n /= 10;
}
return 0;
}
void oper(){
a[0] = 0;
for(int i = 1;i < N;i ++ ){
if(judge(i)) a[i] = a[i-1] + 1;
else a[i] = a[i-1];
}
}
int main(){
oper();//前缀和预处理
int n,m;
while(cin >> n >> m ){
if(n == 0 && m == 0) return 0;
cout << a[m] - a[n - 1];
puts("");
}
return 0;
}
老子的全排列呢
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
老李见和尚赢了自己的酒,但是自己还舍不得,所以就耍起了赖皮,对和尚说,光武不行,再来点文的,你给我说出来1-8的全排序,我就让你喝,这次绝不耍你,你能帮帮和尚么?
输入描述:
无
输出描述:
1~8的全排列,按照全排列的顺序输出,每行结尾无空格。
示例1
输入
No_Input
输出
Full arrangement of 1~8
备注:
1~3的全排列 : 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[10];
for(int i = 1;i <= 8;i ++ )
a[i]=i;
sort(a + 1,a + 1 + 8);//排序
do{
for(int i = 1;i <= 8;i ++ ){
if(i == 1) cout << a[i];
else cout << ' ' << a[i];
}
puts("");
}while(next_permutation(a + 1,a + 1 + 8));//直接用函数不香吗
return 0;
}
N皇后问题
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
给出一个n×n的国际象棋棋盘,你需要在棋盘中摆放nn个皇后,使得任意两个皇后之间不能互相攻击。具体来说,不能存在两个皇后位于同一行、同一列,或者同一对角线。请问共有多少种摆放方式满足条件。
输入描述:
一行,一个整数n(1\le n \le 12)n(1≤n≤12),表示棋盘的大小。
输出描述:
输出一行一个整数,表示总共有多少种摆放皇后的方案,使得它们两两不能互相攻击。
示例1
输入
4
输出
2
#include<bits/stdc++.h>
using namespace std;
int n;
int a[15][15]; //棋盘
int judge_lie[15]; //检查同一列有没有皇后,没放就是0
int judge_zhu[30]; //检查主对角线
int judge_fu[30]; //检查副对角线
int now[15]; //用来暂时存下当前答案
int ans;
void dfs(int i){//i行
if (i > n){//搜索完每一行了
ans++; //答案总数加一
return; //搜索结束,返回上一个情况
}
for (int j = 1; j <= n; j++){//搜索这一行的每一个数据看符不符合要求
if (!judge_lie[j] && !judge_zhu[i + j - 2] && !judge_fu[n - 1 + i - j]){//符合
now[i] = j; //记下第i行是第j个放下了棋子
judge_lie[j] = 1; //下面三行用来记录现在这个棋子的列,对角线都已经不能再放棋子了
judge_zhu[i + j - 2] = 1;
judge_fu[n - 1 + i - j]=1;
dfs(i + 1); //这一行放完了不能再放了,开始在这第i行第j个放下棋子的前提下搜索下一行
judge_lie[j] = 0; //搜索完第i行第j列放棋子的所有后续情况后,拿走,回溯,看看这第i行还有没有其它格子可以放棋子
judge_zhu[i + j - 2] = 0;
judge_fu[n - 1 + i - j] = 0;
now[i] = 0;
}
}
}
int main(){
cin >> n;
dfs(1); //dfs搜索第一行
cout << ans;
return 0;
}
走出迷宫
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
小明现在在玩一个游戏,游戏来到了教学关卡,迷宫是一个N*M的矩阵。
小明的起点在地图中用“S”来表示,终点用“E”来表示,障碍物用“#”来表示,空地用“.”来表示。
障碍物不能通过。小明如果现在在点(x,y)处,那么下一步只能走到相邻的四个格子中的某一个:(x+1,y),(x-1,y),(x,y+1),(x,y-1);
小明想要知道,现在他能否从起点走到终点。
输入描述:
本题包含多组数据。 每组数据先输入两个数字N,M 接下来N行,每行M个字符,表示地图的状态。 数据范围: 2<=N,M<=500 保证有一个起点S,同时保证有一个终点E.
输出描述:
每组数据输出一行,如果小明能够从起点走到终点,那么输出Yes,否则输出No
示例1
输入
3 3
S..
..E
...
3 3
S##
###
##E
输出
Yes
No
#include<bits/stdc++.h>
using namespace std;
const int N = 510;
char a[N][N];
int sign[N][N];
int n,m,flag;
int dx[4] = {1,0,-1,0} , dy[4] = {0,1,0,-1};//坐标的偏移量
void dfs(int sx,int sy){
if(a[sx][sy]=='E') flag = 1;//标记是否走到出口
for(int i = 0;i < 4;i ++ ){
int x = sx + dx[i],y = sy + dy[i];
if(x >= 0&& x < n && y >= 0&& y < m && a[x][y] != '#'&& !sign[x][y]){//前四个是判断当前位置是否出界,第五个是判断所在位置是否为通路,最后判断是否走过
sign[x][y] = 1;//标记当前位置走过了
dfs(x,y);//dfs下一个位置
}
}
}
int main(){
while(cin >> n >> m){
int sx = 0,sy = 0;
//恢复现场
flag = 0;
memset(a ,0, sizeof(a));
memset(sign , 0 , sizeof(sign));
//导入地图
for(int i = 0;i < n;i ++ ){
for(int j = 0;j < m;j ++ ){
cin>>a[i][j];
if(a[i][j] == 'S'){//标记出口的位置
sx = i;sy = j;
}
}
}
dfs(sx,sy);//从起点开始dfs
if(flag) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
【NOIP2018】道路铺设
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld
题目描述
春春是一名道路工程师,负责铺设一条长度为 n 的道路。
铺设道路的主要工作是填平下陷的地表。整段道路可以看作是 n 块首尾相连的区域,一开始,第 i 块区域下陷的深度为 di 。
春春每天可以选择一段连续区间 [L, R] ,填充这段区间中的每块区域,让其下陷深 度减少 1。在选择区间时,需要保证,区间内的每块区域在填充前下陷深度均不为 0 。
春春希望你能帮他设计一种方案,可以在最短的时间内将整段道路的下陷深度都变为0。
输入描述:
输入包含两行,第一行包含一个整数 n,表示道路的长度。 第二行包含 n 个整数,相邻两数间用一个空格隔开,第 i 个整数为 di。
输出描述:
输出文件仅包含一个整数,即最少需要多少天才能完成任务。
示例1
输入
6
4 3 2 5 3 5
输出
9
说明
一种可行的最佳方案是,依次选择: [1,6]、[1,6]、[1,2]、[1,1]、[4,6]、[4,4]、[4,4]、[6,6]、[6,6]。
备注:
对于30%的数据,1 ≤ 𝑛 ≤ 10;
对于70%的数据,1 ≤ 𝑛 ≤ 1000;
对于100%的数据,1 ≤ 𝑛 ≤ 100000,0 ≤ di ≤ 10000 。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n,a[N],f[N];//用f[i]表示前i个坑所铺设的最少天数
int main(){
cin >> n;
for(int i = 1;i <= n;i ++ ) cin >> a[i];
f[1] = a[1];//初始化
for(int i = 2;i <= n;i ++ ){
if(a[i] <= a[i-1]) f[i] = f[i-1];//如果a[i] <= a[i-1],那么在填a[i-1]时就可以顺带把a[i]填上
else f[i] = f[i-1] + (a[i] - a[i-1]);//否则在填a[i-1]时肯定要把a[i]一块填上,而a[i]剩余的就单独填
}
cout << f[n] << endl;
return 0;
}
[NOIP2001]数的划分
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
将整数n分成k份,且每份不能为空,任意两个方案不能相同(不考虑顺序)。
例如:n=7,k=3,下面三种分法被认为是相同的。
1,1,5;
1,5,1;
5,1,1;
问有多少种不同的分法。
输入:n,k ( 6 < n ≤ 200,2 ≤ k ≤ 6 )
输出:一个整数,即不同的分法。
输入描述:
两个整数 n,k ( 6 < n ≤ 200, 2 ≤ k ≤ 6 )
输出描述:
1个整数,即不同的分法。
示例1
输入
7 3
输出
4
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int main(){
int n,k;
cin >> n >> k;
int dp[N][N];
for(int i = 1;i <= n;i ++ ) dp[i][1] = 1;//输出1份即为自身,故为一种方案
for(int i = 1;i <= n;i ++ )
for(int j = 2;j <= k;j ++ )//注意从2开始
// 假设是按递减排列
// n=7,k=3时可以有5 1 1, 4 2 1, 3 3 1, 3 2 2四种拆法,这些拆法可以分成两类,一是以1结尾,二是 >1的数结尾。
// 以1结尾时,必然是把6分成2份然后最后加个1(5 1,4 2,3 3)
// 以大于1的数结尾时说明所有数都大于1,
// 此时只要先把3个位置都放上1,然后把剩下的4分成3份加上去,如3 2 2 -> 2 1 1即把4分成3份。
// dp[i][j] = dp[i-1][j-1](最后为1)+dp[i-j][j](最后大于1)
if(i >= j) dp[i][j] = dp[i-1][j-1] + dp[i-j][j];//n >= k时才能有数分,故i >= j
printf("%d\n",dp[n][k]);//从n中分出k份的方案数
return 0;
}