目录
1.试题 基础练习 杨辉三角形
资源限制
内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
问题描述
杨辉三角形又称Pascal三角形,它的第i+1行是(a+b)i的展开式的系数。
它的一个重要性质是:三角形中的每个数字等于它两肩上的数字相加。
下面给出了杨辉三角形的前4行:
1
1 1
1 2 1
1 3 3 1
给出n,输出它的前n行。
输入格式
输入包含一个数n。
输出格式
输出杨辉三角形的前n行。每一行从这一行的第一个数开始依次输出,中间使用一个空格分隔。请不要在前面输出多余的空格。
样例输入
4
样例输出
1
1 1
1 2 1
1 3 3 1
数据规模与约定
1 <= n <= 34。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1100;
int f[N][N];
int n;
int main()
{
cin>>n;
f[1][1]=1;
for(int i=2;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
f[i][j]=f[i-1][j]+f[i-1][j-1];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
cout<<f[i][j]<<" ";
}
puts("");
}
return 0;
}
2.试题 基础练习 字母图形
资源限制
内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
问题描述
利用字母可以组成一些美丽的图形,下面给出了一个例子:
ABCDEFG
BABCDEF
CBABCDE
DCBABCD
EDCBABC
这是一个5行7列的图形,请找出这个图形的规律,并输出一个n行m列的图形。
输入格式
输入一行,包含两个整数n和m,分别表示你要输出的图形的行数的列数。
输出格式
输出n行,每个m个字符,为你的图形。
样例输入
5 7
样例输出
ABCDEFG
BABCDEF
CBABCDE
DCBABCD
EDCBABC
数据规模与约定
1 <= n, m <= 26。
#include<stdio.h>
int main()
{
char ch[26][26];
int i,j,m,n;
scanf("%d %d",&m,&n);
for(i=0;i<n;i++)
ch[0][i]=i+'A';
for(i=1;i<m;i++)
{
ch[i][0]=i+'A';
for(j=1;j<n;j++)
{
ch[i][j]=ch[i-1][j-1];
}
}
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
printf("%c",ch[i][j]);
}
printf("\n");
}
return 0;
}
3.试题 基础练习 特殊的数字
资源限制
内存限制:512.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
问题描述
153是一个非常特殊的数,它等于它的每位数字的立方和,即153=1*1*1+5*5*5+3*3*3。编程求所有满足这种条件的三位十进制数。
输出格式
按从小到大的顺序输出满足条件的三位十进制数,每个数占一行。
#include <stdio.h>
#include <math.h>
int main() {
int i,a,b,c;
for(i=100;i<1000;i++)
{
a=i/100;
b=i/10%10;
c=i%10;
if(i==pow(a,3)+pow(b,3)+pow(c,3))
{
printf("%d\n",i);
}
}
return 0;
}
4.试题 基础练习 回文数
资源限制
内存限制:512.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
问题描述
1221是一个非常特殊的数,它从左边读和从右边读是一样的,编程求所有这样的四位十进制数。
输出格式
按从小到大的顺序输出满足条件的四位十进制数。
#include<stdio.h>
int main()
{
int i;
int a1,a2,a3,a4;
for(i=1000;i<10000;i++){
a1=i/1000%10;
a2=i/100%10;
a3=i/10%10;
a4=i%10;
if(a1==a4&&a2==a3)
printf("%d\n",i);
}
return 0;
}
5.试题 基础练习 2n皇后问题
问题描述
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式
输入的第一行为一个整数n,表示棋盘的大小。
接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式
输出一个整数,表示总共有多少种放法。
样例输入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
2
样例输入
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
0
思路
2n皇后问题和8皇后问题思路几乎没有区别,可按照全排列的搜索顺序:
依次每一行放一个皇后,放在某一列,dfs遍历所有可能值(如n=3时有 123 132 213 231 312 321)
剪枝,排除有行列对角线冲突的情况
(1)先放黑皇后,检查格子是否为1及有无行列对角线冲突
(2)再放白皇后,检查格子是否为1及有无行列对角线冲突,以及有无黑皇后
注意:看行列对角线冲突时,黑的是黑的,白的是白的,都是两者的内部冲突,相互不干扰
最终anser即,每种黑皇后的结果中白皇后anser的和.
#include<iostream>
#include<cstdio>
using namespace std;
const int N = 20;
int n, ans;
bool mp[N][N], b[N][N];
bool bdui[N], budui[N], bcol[N];
bool wdui[N], wudui[N], wcol[N];
void white(int u){//后放
if(u == n){
ans ++;
return;
}
for(int i = 0; i < n; i ++ )
if(!wcol[i] && !wdui[u + i] && !wudui[i - u + n] && mp[u][i] && !b[u][i]){
wcol[i] = wdui[u + i] = wudui[i - u + n] = true;
white(u + 1);
wcol[i] = wdui[u + i] = wudui[i - u + n] = false;
}
}
void black(int u){//先放
if(u == n){
white(0);
return;
}
for(int i = 0; i < n; i ++ )
if(!bcol[i] && !bdui[u + i] && !budui[i - u + n] && mp[u][i]){
b[u][i] = true;
bcol[i] = bdui[u + i] = budui[i - u + n] = true;
black(u + 1);
bcol[i] = bdui[u + i] = budui[i - u + n] = false;
b[u][i] = false;
}
}
int main(){
cin >> n;
for(int i = 0; i < n; i ++ )
for(int j = 0; j < n; j ++ )
scanf("%d", &mp[i][j]);
black(0);
cout << ans << endl;
return 0;
}
6.试题 算法训练 单词接龙
问题描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at 和 atide 间不能相连。
输入格式
输入的第一行为一个单独的整数n (n<=20)表示单词数,以下n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.
输出格式
只需输出以此字母开头的最长的“龙”的长度
样例输入
5
at
touch
cheat
choose
tact
a
样例输出
23
样例说明
连成的“龙”为atoucheatactactouchoose
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=21;
int n;//单词数
string str[N];//怎么说也要让输入的那些单词有 地方住呀
//这里的N表示单词数的最多的个数限度
int g[N][N]={0};//两个单词之间能够重合的最短长度
int ans=0;//记录龙的长度
int used[N]={0};//每个单词使用的次数
void dfs(string dragon,int last)
{
ans=max((int)dragon.size(),ans);
//现在龙的长度,强制转换是因为string的size是无符号长整型
used[last]++;//使用次数+1
//寻找它的下一个单词
for(int i=0;i<n;i++)
{
if(g[last][i]&&used[i]<2)//如果跟第i个单词有重复部分,就接上
dfs(dragon+str[i].substr(g[last][i]),i);
}
used[last]--;
//我来解释一下大多数blog都没讲到的为什么要恢复现场
//就好比例子来说,touch是第一个被接上的单词
//那么这个touch在履行完它接龙的责任之后这个循环就结束了呀
//本来是要由于递归回到at的让人家at继续挑选看看能不能接上其他重合的单词的另一条龙
//那么好嘞,你at要接上另一条龙了,就说明龙里面已经不是touch作老二了
//那你是不是要把人家touch还回去,要用的时候再借嘛
//ok,就是这样。
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
cin>>str[i];
char sign;
cin>>sign;//给定一个开头字母
//为了枚举字符串之间相同的字串合并形式
//必须有预处理出来的字符串之间的相同子串邻接表
//总不能一遍一遍算吧,得有个表
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)//也有可能跟自己egtact
{
string a=str[i];//当前的单词
string b=str[j];//被对照的单词
for(int k=1;k<min(a.size(),b.size());k++)
//不用等于是因为不能是包含关系
//k表示重复的字串的字符个数
{
if(a.substr(a.size()-k)==b.substr(0,k))
//求最小相同字串才能得出最长的龙
//重合的越多,龙越短
{
g[i][j]=k;
break;
}
}
}
}
for(int i=0;i<n;i++)//从第一个单词开始
{
if(str[i][0]==sign)
dfs(str[i],i);
//第一个参数代表现在的龙的现状
//第二个参数代表此时操作的单词的坐标
}
cout<<ans;
return 0;
}
7.试题 算法训练 粘木棍
资源限制
内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
问题描述
有N根木棍,需要将其粘贴成M个长木棍,使得最长的和最短的的差距最小。
输入格式
第一行两个整数N,M。
一行N个整数,表示木棍的长度。
输出格式
一行一个整数,表示最小的差距
样例输入
3 2
10 20 40
样例输出
10
数据规模和约定
N, M<=7
思路:每个木棍在分成m堆时,每堆都可以选择粘或者不粘,用dfs枚举所有方案然后找出来最小即可。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int N=10;
int a[N];
bool st[N];
int add[N];
int n,m;
int ans=1e9;
void dfs(int u)
{
if(u>n)
{
for(int i=1;i<=n;i++)
if(!st[i]) return ;
int Max=add[1],Min=add[1];
for(int i=2;i<=m;i++)
{
Max=max(Max,add[i]);
Min=min(Min,add[i]);
}
ans=min(ans,Max-Min);
return ;
}
for(int i=1;i<=m;i++)
{
//粘
add[i]+=a[u];
st[u]=true;
dfs(u+1);
add[i]-=a[u];
st[u]=false;
//不粘
dfs(u+1);
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
dfs(1);
cout<<ans<<endl;
return 0;
}