第七周习题
菜鸡记录站
- A、Welcome
- 代码
- B、第K大元素
- 代码
- C、整数划分问题之备忘录法
- 代码
- D、数字三角形之备忘录法
- 代码
- E、数字三角形之动态规划法
- 代码
- F、滚球游戏
- 代码
A、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
代码
import java.util.Scanner;
public class Main {
static int n = 0;
public static void output_dot(){
for (int i = 1; i <= n; i++)
System.out.print(".");
}
private static void output_letter(){
System.out.print("o...o");
output_dot();
System.out.print("o...o");
output_dot();
System.out.print("o...o");
output_dot();
System.out.print("ooooo");
output_dot();
System.out.print("o...o\n");
System.out.print("o...o");
output_dot();
System.out.print("oo..o");
output_dot();
System.out.print("o...o");
output_dot();
System.out.print("o....");
output_dot();
System.out.print("oo.oo\n");
System.out.print("ooooo");
output_dot();
System.out.print("o.o.o");
output_dot();
System.out.print("o...o");
output_dot();
System.out.print("o....");
output_dot();
System.out.print("o.o.o\n");
System.out.print("o...o");
output_dot();
System.out.print("o..oo");
output_dot();
System.out.print("o...o");
output_dot();
System.out.print("o....");
output_dot();
System.out.print("o...o\n");
System.out.print("o...o");
output_dot();
System.out.print("o...o");
output_dot();
System.out.print("ooooo");
output_dot();
System.out.print("ooooo");
output_dot();
System.out.print("o...o\n");
}
public static void main(String[]args){
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
output_letter();
}
}
链接:Welcome——记得戳我呀!
【我看了别人的文章看懂了题目的意思,可是我不会写啊,所以我把人家的代码直接拿过来了,别骂我,我会努力的,我只是修改了一些名称】
B、第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 {
private static void swap(int[] shuzu, int i, int j) {
int t=shuzu[i];
shuzu[i]=shuzu[j];
shuzu[j]=t;
}
private static int fenqu(int[] shuzu, int left, int right) {
// TODO Auto-generated method stub
int r = random(left,right);
swap(shuzu,left,r);
int jizhun = shuzu[left];//基準
while (left < right) { // 最终使得枢纽之前(后)的记录均不大(小)于它
while (left < right && shuzu[right] >= jizhun)
right--;
swap(shuzu, left, right);// 将比枢轴记录小的记录交换到低端
while (left < right && shuzu[left] <= jizhun)
left++;
swap(shuzu, left, right); // 将比枢轴大的记录交换到高端
}
return left;
}
private static int kuaipai(int[] shuzu, int left, int right, int key) {
if(left==right)
return shuzu[left];
int r = fenqu(shuzu,left,right);//p,q兩個端點,分區縮小範圍
int j = r-left+1;//基准前包括基准的个数,从第1小到第j小元素
if(key<=j)
return kuaipai(shuzu,left,r,key);
else
return kuaipai(shuzu,r+1,right,key-j);
}
private static int random(int a, int b) { //【a,b】
Random rand=new Random();
int k = rand.nextInt(b-a+1)+a;
return k;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int[] shuzu = new int[n];
for (int i = 0; i < n; i++) {
shuzu[i]= sc.nextInt();
}
int shuju = sc.nextInt();
int key = shuzu.length-shuju+1;
System.out.println(kuaipai(shuzu,0,n-1,key);
}
}
}
链接:第K大元素——戳这里!
【这个题我刚开始不知道怎么做,然后就看了别人的代码,就是把求第K大元素变成了求第Z小元素,然后求出这个Z就OK,只是我懂了,但是我不会写啊,然后就把前几周写的代码拿过来,又看着别人的代码改啊】
C、整数划分问题之备忘录法
题目描述
- 使用备忘录法编写一个程序,求一个正整数n的所有划分个数。 例如,输入3,输出3;输入4,输出5。
输入
- 多组输入,每一组是一个正整数n。
输出
- 输出划分数。
样例输入 Copy
3
4
样例输出 Copy
3
5
代码
import java.util.Scanner;
public class Main {
static int shuzu[][]=new int[105][105];
static int n;
public static int memory(int n,int m) {
if((n<1)||(m<1)) //小于0无意义
return 0;
if((n==1)||(m==1)) //其中一个为0, q(n,m)=0 n=1 || m=1
return 1;
if(n<m) //q(n,m)=q(n,n)
return memory(n,n);
if(n==m){ //q(n,m)=q(n,n)=1+q(n,n-1)
if (shuzu[n-1][n-2]==0) { //数组中不存在已计算过的值
shuzu[n-1][n-2] = memory(n,n-1);//记录下来
}
return 1 + shuzu[n-1][n-2];
}
if (n>m) { //q(n,m)=q(n,m-1)+q(n-m,m)
if (shuzu[n-m-1][m-1]==0) {
shuzu[n-m-1][m-1]=memory(n-m,m);
}
if (shuzu[n-1][m-2]==0) {
shuzu[n-1][m-2] = memory(n,m-1);
}
return shuzu[n-1][m-2] + shuzu[n-m-1][m-1];
}
else
return 0;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
n = sc.nextInt();
System.out.println(memory(n,n));
}
}
}
链接自取:整数划分之备忘录法——戳我戳我!
【冒个泡证明我还在~】
D、数字三角形之备忘录法
题目描述
如下图所示的数字三角形,从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,和最大的路径称为最佳路径。编写一个程序求出最佳路径上的数字之和。
【使用动态规划法实现】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
提示
- 路径上的每一步只能从一个数走到下一层上和它最近的左边的数或者右边的数。
代码
import java.util.Scanner;
public class Main {
static int shuzu[][]=new int [105][105];
static int cbb[][]=new int[105][105];
static int n;
private static int solve(int i,int j) {
//超出范围,结束递归
if(shuzu[i][j]>=0)
return shuzu[i][j]; //引入备忘录保存子问题的解
if(i==n+1)
return 0;
return shuzu[i][j]=cbb[i][j]+Math.max(solve(i+1,j),solve(i+1,j+1));
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
n=sc.nextInt();
for(int i=1;i<=n;i++) {
for(int j=1;j<=i;j++) {
cbb[i][j]=sc.nextInt();
shuzu[i][j]=-1;
}
}
System.out.println(solve(1,1));
}
}
}
放个链接:数字三角形之备忘录法
【希望我还能见到明天的太阳,哭晕在厕所~,一次次的失败和一次次的尝试,我麻木了,我先看个漫画】
E、数字三角形之动态规划法
题目描述
如下图所示的数字三角形,从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,和最大的路径称为最佳路径。编写一个程序求出最佳路径上的数字之和。
【使用动态规划法实现】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
提示
- 路径上的每一步只能从一个数走到下一层上和它最近的左边的数或者右边的数。
代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int n = sc.nextInt();
int cbb[][] = new int[n+1][n+1];
int shuzu[][] = new int[n+1][n+1];
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
cbb[i][j] = sc.nextInt();
for(int i=1;i<=n;i++)
shuzu[n][i] = cbb[n][i];//最后一行的每一列
for(int i=n-1;i>=1;i--)
for(int j=1;j<=i;j++) //自底向上DP
shuzu[i][j]=cbb[i][j]+Math.max(shuzu[i+1][j],shuzu[i+1][j+1]);//对行遍历
System.out.println(shuzu[1][1]);
}
}
}
放个链接: 数字三角形之动态规划法
【我也不好意思说啥了,我觉得有CSDN这个地方挺好的,但是我养成了依赖性,不会做就立马搜题,也不会说自己去思考,反正我自己是深有体会的,而且最近几次上课也没有认真听讲,上课老神游,唉~觉得自己真是越来越丧了呢,得快点写了,该睡觉了】
F、滚球游戏
题目描述
- 某滚球游戏规则如下:球从入口处(第一层)开始向下滚动,每次可向下滚动一层,直到滚至最下面一层为止。球每次可滚至左下、下方或右下三个方格中的任意一个,每个方格都有一个得分,如样例所示。第1层有1个方格,第2层有3个方格,……,以此类推,第n层有2*n-1个方格。设计一个算法,使得球从入口滚至最下面一层的总得分和最大。
输入
- 对于每个样例,第1行的正整数n表示数字三角形的行数。(n<=100)
- 接下来n行包含一个数字三角形,每一行包含2n-1个方格,对应有2n-1个表示得分的正整数(不超过10^5),每两个数字之间用空格隔开。
- 每两组样例之间有一个空行。
输出
- 球从入口(第一层)滚至最下面一层的最大得分和。
样例输入 Copy
2
3
2 1 3
3
1
2 1 2
3 4 2 1 3
样例输出 Copy
6
7
【这题我真是哭死QAQ~,我花了一天的时间在这个题目上,我起初CSDN,只找到了一个人的代码,然后我就复制过来了,结果不报错,运行不输出数据,我又去百度,我在那个preferences里勾选两个show的框,取消框里的√,我又重启又改代码,愣是没有输出,我整个人都傻了,然后我就放弃了,我想着等着我的大佬室友从自习教室回来帮我看看,然后一直等到了晚上11点多,我还在这个题目,而且提交时间快截止了,我的大佬室友之一说:“我不看JAVA代码,我比熟悉C语言”,是的没错,我又傻了,正如我现在写代码第一反应是java代码一样,看C语言我一脸懵逼,我又问了另一个大佬,好家伙,“我看不懂你的代码”,是我不配了,我自己来写吧,我把之前借鉴的那个代码的输入改了,不然它要我无限输入,我又新写了一个函数,来判断三个数的大小(得益于我的室友,她的指导还是有帮助的),然后直接用了数字三角形的那段动态规划的代码,终于,含泪告别第七周的习题了,有些时候,放手去写吧,相信自己,哭QAQ,终于可以休息会了,写个博客先!】
放个链接,就是我最初看到的那篇文章,其实不用切割空格,反正我写的代码就没用,不过还是可以看看啦:滚球游戏 ——DP
代码
import java.util.Scanner;
public class Main {
public static int max_da(int i,int j,int t){
int a = Math.max(i, j);
int b = Math.max(j, t);
int c = Math.max(a, b);
return c;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int n = sc.nextInt();
int a[][] = new int[n+1][2*n];
int p[][] = new int[n+1][2*n];
for(int i=1;i<=n;i++)
for(int j=1;j<=2*i-1;j++)
a[i][j] = sc.nextInt();//每一行每一列
for(int j=1;j<=2*n-1;j++)
p[n][j] = a[n][j];//最后一行的每一列
for(int i=n-1;i>=1;i--)
for(int j=1;j<=2*i-1;j++) //自底向上DP
p[i][j]=a[i][j]+max_da(p[i+1][j],p[i+1][j+1],p[i+1][j+2]);//对行遍历
System.out.println(p[1][1]);
}
}
}
【今天学习到的小技能:我真是好懒呀!
1、Ctrl + / 可以给选定的代码段加单行注释,取消也用这个快捷键
2、Ctrl + Shift + / 多行注释,取消也是这个,记得选中再按键哈
3、Ctrl + D 删除某一行,鼠标放在这一行
】
还没有评论,来说两句吧...