hnucm-oj1174 - 2021年春季学期《算法分析与设计》练习7
A 1365: Welcome
题目描述
”How happy we are, To meet friends from afar!”
Welcome to Hunan University of Chinese Medicine!
Hope all of you can enjoy the competition ^ v ^
Now your task is to read an integer w and output the character painting of ”HNUCM”, there are w
space(s) (space are represented by dot) between two letters. Please refer to the sample for the specific
format.
输入
There are several test files and each contains one case.
The input contains only 1 integer w (1 ≤ w ≤ 2018).
输出
The output has 5 lines, each line has 25+4w characters which only contains ’o’(lowercase letter ’o’) and
’.’(English period ’.’)
样例输入 Copy
1
样例输出 Copy
o…o.o…o.o…o.ooooo.o…o
o…o.oo…o.o…o.o…oo.oo
ooooo.o.o.o.o…o.o…o.o.o
o…o.o…oo.o…o.o…o…o
o…o.o…o.ooooo.ooooo.o…o
#include <stdio.h>
#include <stdlib.h>
int main(){
int n,i,flag,j;
while(scanf("%d",&n)!=EOF){
char a[25]={'o','.','.','.','o','o','.','.','.','o','o','.','.','.','o','o','o','o','o','o','o','.','.','.','o'};
char b[25]={'o','.','.','.','o','o','o','.','.','o','o','.','.','.','o','o','.','.','.','.','o','o','.','o','o'};
char c[25]={'o','o','o','o','o','o','.','o','.','o','o','.','.','.','o','o','.','.','.','.','o','.','o','.','o'};
char d[25]={'o','.','.','.','o','o','.','.','o','o','o','.','.','.','o','o','.','.','.','.','o','.','.','.','o'};
char e[25]={'o','.','.','.','o','o','.','.','.','o','o','o','o','o','o','o','o','o','o','o','o','.','.','.','o'};
flag=0;
for(i=0;i<25;i++){
if(flag==5){
for(j=0;j<n;j++)
printf(".");
flag=0;
}
printf("%c",a[i]);
flag++;
}
printf("\n");
flag=0;
for(i=0;i<25;i++){
if(flag==5){
for(j=0;j<n;j++)
printf(".");
flag=0;
}
printf("%c",b[i]);
flag++;
}
printf("\n");
flag=0;
for(i=0;i<25;i++){
if(flag==5){
for(j=0;j<n;j++)
printf(".");
flag=0;
}
printf("%c",c[i]);
flag++;
}
printf("\n");
flag=0;
for(i=0;i<25;i++){
if(flag==5){
for(j=0;j<n;j++)
printf(".");
flag=0;
}
printf("%c",d[i]);
flag++;
}
printf("\n");
flag=0;
for(i=0;i<25;i++){
if(flag==5){
for(j=0;j<n;j++)
printf(".");
flag=0;
}
printf("%c",e[i]);
flag++;
}
printf("\n");
}
}
B 1434: 第k大元素问题
题目描述
输入n个整数和一个正整数k(1<=k<=n),输出这些整数从大到小排序后的第k个。(要求时间复杂度为O(n),需使用随机化分区) 。
输入
多组数据输入,每组第一个数字为数组的长度n, 然后接下输入n个整数,最后输入整数k(1<=k<=n)。
输出
输出数组降序排序后的第k个整数。
样例输入 Copy
5 1 5 2 4 3 3
6 1 2 3 4 5 6 1
样例输出 Copy
3
6
import java.util.Random;
import java.util.Scanner;
public class Main {
static int random_sort(int a,int b) {
Random rand=new Random();
int n=rand.nextInt(b-a+1)+a;
return n;
}
static int quickselect(int a[],int s,int t,int k) {
if(s==t)
return a[s];
int i=rand_partition(a,s,t);
int j=i-s+1;
if(k<=j)
return quickselect(a,s,i,k);
else
return quickselect(a,i+1,t,k-j);
}
static void swap(int a[],int i,int j){
int t=a[i];
a[i]=a[j];
a[j]=t;
}
static int rand_partition(int a[],int p,int q) {
int i=random_sort(p,q);
swap(a,p,i);
int r=partition(a,p,q);
return r;
}
static int partition(int a[],int p,int q){
int x=a[p],i=p,j;
for(j=p+1;j<=q;j++){
if(a[j]>=x){
i++;
swap(a,i,j);
}
}
swap(a,p,i);
return i;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scan=new Scanner(System.in);
while(scan.hasNextInt()) {
int n=scan.nextInt();
int a[]=new int[n];
for(int i=0;i<n;i++) {
a[i]=scan.nextInt();
}
int k=scan.nextInt();
int res=quickselect(a,0,n-1,k);
System.out.println(res);
}
}
}
C 1690: 整数划分问题之备忘录法
题目描述
使用备忘录法编写一个程序,求一个正整数n的所有划分个数。
例如,输入3,输出3;输入4,输出5。
输入
多组输入,每一组是一个正整数n。
输出
输出划分数。
样例输入 Copy
3
4
样例输出 Copy
3
5
#include <stdio.h>
#include <stdlib.h>
int num[100][100];
int f(int n,int m){
if((n<1)||(m<1)){
return 0;
}
if((n==1)||(m==1)){
return 1;
}
if(n<m)
return f(n,n);
if(n==m){
if(num[n-1][n-2]==0)
num[n-1][n-2]=f(n,n-1);
return 1+num[n-1][n-2];
}
if(n>m){
if(num[n-1][m-2]==0)
num[n-1][m-2]=f(n,m-1);
if(num[n-m-1][m-1]==0)
num[n-m-1][m-1]=f(n-m,m);
return num[n-1][m-2]+num[n-m-1][m-1];
}
}
int main(){
int a;
while(scanf("%d",&a)!=EOF){
int b=f(a,a);
printf("%d\n",b);
}
}
D 1436: 数字三角形之备忘录法
题目描述
如下图所示的数字三角形,从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,和最大的路径称为最佳路径。编写一个程序求出最佳路径上的数字之和。 【使用备忘录法实现】
7
3 8
8 1 2
2 7 4 4
4 5 2 6 5
输入
多组样例输入,每组第一行输入三角形的层数n,接下来n行输入三角形。
输出
输出最佳路径上的数字之和。
样例输入 Copy
2
1
1 2
3
1
1 2
1 2 3
样例输出 Copy
3
6
提示
路径上的每一步只能从一个数走到下一层上和它最近的左边的数或者右边的数。
#include <stdio.h>
#include <stdlib.h>
int p[100][100],a[100][100],n;
int max(int g,int h){
if(g>h)
return g;
else
return h;
}
int f(int i,int j){
if(p[i][j]>=0)
return p[i][j];
if(i==n+1)
return 0;
return p[i][j]=a[i][j]+max(f(i+1,j),f(i+1,j+1));
}
int main(){
while(scanf("%d",&n)!=EOF){
for(int k=0;k<=n;k++){
for(int w=0;w<=n;w++){
p[k][w]=-1;
}
}
for(int k=1;k<=n;k++){
for(int w=1;w<=k;w++){
scanf("%d",&a[k][w]);
}
}
f(1,1);
printf("%d\n",p[1][1]);
}
}
E 1463: 数字三角形之动态规划法
题目描述
如下图所示的数字三角形,从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,和最大的路径称为最佳路径。编写一个程序求出最佳路径上的数字之和。 【使用动态规划法实现】
7
3 8
8 1 2
2 7 4 4
4 5 2 6 5
输入
多组样例输入,每组第一行输入三角形的层数n,接下来n行输入三角形。
输出
输出最佳路径上的数字之和。
样例输入 Copy
2
1
1 2
3
1
1 2
1 2 3
样例输出 Copy
3
6
提示
路径上的每一步只能从一个数走到下一层上和它最近的左边的数或者右边的数。
#include <stdio.h>
#include <stdlib.h>
int p[100][100],a[100][100],n;
int max(int g,int h){
if(g>h)
return g;
else
return h;
}
int f(){
for(int i=1;i<=n;i++)
p[n][i]=a[n][i];
for(int i=n-1;i>=1;i--){
for(int j=1;j<=i;j++){
p[i][j]=a[i][j]+max(p[i+1][j],p[i+1][j+1]);
}
}
}
int main(){
while(scanf("%d",&n)!=EOF){
for(int k=0;k<=n;k++){
for(int w=0;w<=n;w++){
p[k][w]=-1;
}
}
for(int k=1;k<=n;k++){
for(int w=1;w<=k;w++){
scanf("%d",&a[k][w]);
}
}
f();
printf("%d\n",p[1][1]);
}
}
F 1751: 滚球游戏
题目描述
某滚球游戏规则如下:球从入口处(第一层)开始向下滚动,每次可向下滚动一层,直到滚至最下面一层为止。球每次可滚至左下、下方或右下三个方格中的任意一个,每个方格都有一个得分,如样例所示。第1层有1个方格,第2层有3个方格,……,以此类推,第n层有2n-1个方格。设计一个算法,使得球从入口滚至最下面一层的总得分和最大。
输入
对于每个样例,第1行的正整数n表示数字三角形的行数。(n<=100)
接下来n行包含一个数字三角形,每一行包含2n-1个方格,对应有2*n-1个表示得分的正整数(不超过10^5),每两个数字之间用空格隔开。
每两组样例之间有一个空行。
输出
球从入口(第一层)滚至最下面一层的最大得分和。
样例输入 Copy
2
3
2 1 3
3
1
2 1 2
3 4 2 1 3
样例输出 Copy
6
7
#include <stdio.h>
#include <stdlib.h>
int p[120][120],a[120][120],n;
int max(int g,int h,int v){
int t=0;
if(g>h)
t=g;
else
t=h;
if(v>t)
return v;
else
return t;
}
int f(){
for(int i=1;i<=2*n-1;i++)
p[n][i]=a[n][i];
for(int i=n-1;i>=1;i--){
for(int j=1;j<=2*i-1;j++){
p[i][j]=a[i][j]+max(p[i+1][j],p[i+1][j+1],p[i+1][j+2]);
}
}
}
int main(){
while(scanf("%d",&n)!=EOF){
for(int k=0;k<=n;k++){
for(int w=0;w<=n;w++){
p[k][w]=-1;
}
}
for(int k=1;k<=n;k++){
for(int w=1;w<=2*k-1;w++){
scanf("%d",&a[k][w]);
}
}
f();
printf("%d\n",p[1][1]);
}
}
G 1058: 大还是小?
题目描述
输入两个实数,判断第一个数大,第二个数大还是一样大。每个数的格式为:
[整数部分].[小数部分]
简单起见,整数部分和小数部分都保证非空,且整数部分不会有前导 0。不过,小数部分的最 后可以有 0,因此 0.0和 0.000是一样大的。
输入
输入包含不超过 20组数据。每组数据包含一行,有两个实数(格式如前所述)。每个实数都 包含不超过 100个字符。
输出
对于每组数据,如果第一个数大,输出"Bigger"。如果第一个数小,输出"Smaller"。如果两个 数相同,输出"Same"。
样例输入 Copy
1.0 2.0
0.00001 0.00000
0.0 0.000
样例输出 Copy
Case 1: Smaller
Case 2: Bigger
Case 3: Same
#include <stdio.h>
#include <stdlib.h>
void max(double m,double n){
if(m>n)
printf("Bigger\n");
if(m<n)
printf("Smaller\n");
if(m==n)
printf("Same\n");
}
int main(){
double m,n;
int i=0;
while(scanf("%lf%lf",&m,&n)!=EOF){
i++;
printf("Case ");
printf("%d: ",i);
max(m,n);
}
}