package com.lanqiao.十一届省赛第二场Java大学B组;
public class Class_01门牌制作 {
public static void main(String[] args) {
int ans=0;
for (int i = 1; i <= 2020; i++) {
String str=i+"";
for (int j = 0; j < str.length(); j++) {
if (str.charAt(j)=='2') {
ans++;
}
}
}
System.out.println(ans);//624
}
}
运行结果为624
package com.lanqiao.十一届省赛第二场Java大学B组;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class Class_02寻找2020 {
public static void main(String[] args) throws Exception {
// int[][] arr= {
// {2,2,0,0,0,0},
// {0,0,0,0,0,0},
// {0,0,2,2,0,2},
// {0,0,0,0,0,0},
// {0,0,0,0,2,2},
// {0,0,2,0,2,0}
// };
BufferedReader bf=new BufferedReader(new InputStreamReader(new FileInputStream("D:\\2020.txt")));
String s="";
char[][] arr=new char[300][];
int cur=0;
int ans=0;
while((s=bf.readLine())!=null) {
arr[cur++]=s.toCharArray();
}
//按行
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length-3; j++) {
if (arr[i][j]==2&&arr[i][j+1]==0&&arr[i][j+2]==2&&arr[i][j+3]==0) {
ans++;
}
}
}
//按列
for (int i = 0; i < arr[1].length; i++) {
for (int j = 0; j < arr.length-3; j++) {
if (arr[j][i]==2&&arr[j+1][i]==0&&arr[j+2][i]==2&&arr[j+3][i]==0) {
ans++;
}
}
}
//按斜线(左上到右下)
for (int i = 0; i < arr.length-3; i++) {
for (int j = 0; j < arr[i].length-3; j++) {
if (arr[i][j]==2&&arr[i+1][j+1]==0&&arr[i+2][j+2]==2&&arr[i+3][j+3]==0) {
ans++;
}
}
}
System.out.println(ans);//16520,可惜没那个txt文件。
}
}
package com.lanqiao.十一届省赛第二场Java大学B组;
public class Class_03蛇形填数 {
public static void main(String[] args) {
//1行1列:1
//2行2列:5=1X4+1
//3行3列:13=1+1X4+2X4
//4行4列:25=1+1X4+2X4+3X4 有规律啊
System.out.println(f(20));//761
}
static int f(int n) {
if (n==1) {//1行1列
return 1;
}
return f(n-1)+4*(n-1);
}
}
package com.lanqiao.十一届省赛第二场Java大学B组;
//dfs+并查集
public class Class_04七段码 {
static int[][] e=new int[8][8];
static int[] use=new int[8];//存储使用的灯=1表示使用啦。
static int[] fa=new int[8];//存储每个点的父节点
static int ans;//记录亮灯的方案数
static int find(int x) {//查找x的根节点
if (x==fa[x]) {
return x;
}
return fa[x]=find(fa[x]);//查找的过程中路径压缩
}
static void init() {
// a b c d e f g
// 1 2 3 4 5 6 7
//1表示直接连通,0表示未直接连通
e[1][2]=e[1][6]=1;
e[2][1]=e[2][3]=e[2][7]=1;
e[3][2]=e[3][4]=e[3][7]=1;
e[4][3]=e[4][5]=1;
e[5][4]=e[5][6]=e[5][7]=1;
e[6][5]=e[6][7]=e[6][1]=1;
e[7][2]=e[7][3]=e[7][5]=e[7][6]=1;
}
static void dfs(int d) {
if (d>7) {
//并查集的初始化
for (int i = 1; i <= 7; i++) {
fa[i]=i;
}
for (int i = 1; i <= 7; i++) {
for (int j = 1; j <= 7; j++) {
if (e[i][j]==1&&use[i]==1&&use[j]==1) {
int fx=find(i);
int fy=find(j);
if (fx!=fy) {
fa[fx]=fy;//并查集合合并
}
}
}
}
int k=0;
for (int i = 1; i <= 7; i++) {
if (use[i]==1&&fa[i]==i) {//亮的灯都在一个集合中,它的根节点的父节点指向自身
k++;
}
}
if (k==1) {
ans++;
}
return;//返回空,表示这个分支的亮灯方案已经处理了
}
use[d]=1;//d这个灯亮了的前提下,所有亮灯方案
dfs(d+1);
use[d]=0;//d这个灯不亮了的前提下,所有亮灯方案
dfs(d+1);
}
public static void main(String[] args) {
init();
dfs(1);
System.out.println(ans);//80
}
}
package com.lanqiao.十一届省赛第二场Java大学B组;
import java.util.Scanner;
public class Class_05排序 {
//https://blog.csdn.net/lena7/article/details/115518747
//ONMLKJIHGFEDCBA交换的次数是105,J移到第一位,可减少5次交换
//JONMLKIHGFEDCBA
}
package com.lanqiao.十一届省赛第二场Java大学B组;
import java.util.Scanner;
public class Class_06成绩分析 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int[] arr=new int[n];
for (int i = 0; i < arr.length; i++) {
arr[i]=scanner.nextInt();
}
int max=arr[0];
int min=arr[0];
double ans=0;
double avg;
for (int i = 0; i < arr.length; i++) {
if (arr[i]>max) {
max=arr[i];
}
if (arr[i]<min) {
min=arr[i];
}
ans+=arr[i];
}
avg=ans/n;
System.out.println(max);
System.out.println(min);
System.out.printf("%.2f",avg);
}
}
package com.lanqiao.十一届省赛第二场Java大学B组;
import java.util.Scanner;
public class Class_07单词分析 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
String str=scanner.nextLine();
int[] temp=new int[26];//记录字符出现的次数
for (int i = 0; i < temp.length; i++) {
temp[i]=0;
}
for (int i = 0; i < str.length(); i++) {
char a=str.charAt(i);
temp[a-'a']++;
}
int maxIndex=0;
int max = 0;
for (int i = 0; i < temp.length; i++) {
if (temp[i]>max) {
max=temp[i];
maxIndex=i;
}
}
System.out.println((char)(maxIndex+'a'));
System.out.println(max);
}
}
package com.lanqiao.十一届省赛第二场Java大学B组;
import java.util.Scanner;
public class Class_08数字三角形 {
static int[][] arr;//存档三角形
static int N;//行
static int[][] ans;//路径和
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int N=scanner.nextInt();
arr=new int[N+1][N+1];
ans=new int[N+1][N+1];//不考虑左右相差的步数,ans[i][j]表示起点(1,1)到(i,j)的路径和
//最后确定的位置决定了左右相差的步数,相差步数不超过1,意味着取最后一行中间的值(N为奇数)
//或取中间两个数的值(N为偶数)
for (int i = 1; i < arr.length; i++) {
for (int j = 1; j <=i ; j++) {
arr[i][j]=scanner.nextInt();
}
}
ans[1][1]=arr[1][1];
for (int i = 2; i < arr.length; i++) {
for (int j = 1; j <=i ; j++) {
if (j==1) {
ans[i][j]=ans[i-1][j]+arr[i][j];
}else if (j==i) {
ans[i][j]=ans[i-1][j-1]+arr[i][j];
}else {
ans[i][j]=Math.max(ans[i-1][j-1]+arr[i][j], ans[i-1][j]+arr[i][j]);
}
}
}
if (N%2==1) {//奇数,左右相差不超过1,就决定终点的位置
int t=(N+1)/2;
System.out.println(ans[N][t]);
}else {//偶数
int t=(N-1)/2;
int p=(N+1)/2;
System.out.println(Math.max(ans[N][t], ans[N][p]));
}
}
}
package com.lanqiao.十一届省赛第二场Java大学B组;
import java.util.Scanner;
public class Class_09子串分值和 {
static int[] temp=new int[26];//temp[i]表示(i+'a')字符出现的次数
static int f(String str) {
for (int i = 0; i < temp.length; i++) {
temp[i]=0;
}
for (int i = 0; i < str.length(); i++) {
char a=str.charAt(i);
temp[a-'a']++;
}
int ans=0;
for (int i = 0; i < temp.length; i++) {
if(temp[i]!=0) {
ans++;
}
}
return ans;
}
//暴力枚举每个子串
static int sum1(String s) {
int ans=0;
for (int i = 0; i < s.length(); i++) {
String string="";
for (int j = i; j < s.length(); j++) {
string=string+s.charAt(j);
ans+=f(string);
}
}
return ans;
}
//优化,按列来,对于该字符,有多少个子串中该字符是有效。遍历字符串得所有符合要求的子串的和即为本题的结果
static long sum2(String s) {
// long start=System.currentTimeMillis();
int len=s.length();
int[] pre=new int[len];
for (int i = 0; i < pre.length; i++) {
pre[i]=-1;//表示i处的字符前面没有与此相同的字符
}
//pre初始化,主要的时间花在这,大概平均时间复杂度O(10^9),但内存循环实际会结束的比较快
pre[0]=-1;
for (int i = 1; i < s.length(); i++) {
for (int j = i-1; j >= 0; j--) {
if (s.charAt(i)==s.charAt(j)) {
pre[i]=j;
break;//退出循环,找到最近的前驱,就退出循环,所以实际上这层循环会结束比较快
}
}
}
long ans=0;
for (int i = 0; i < len; i++) {
// pre[x] x
// ......a.......a..........
//s[i...j]子串中a是有效字符的,则pre[x]<i<=x,x<=j<len,这样的s[i...j]有多少种。
ans+=(i-pre[i])*(len-i);//构建符合要求的子串,包含i处字符的子串中有pre[i]处的字符,则这个子串不能算。否则同样的字符算了两次
}
// System.out.println(System.currentTimeMillis()-start);
return ans;
}
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
String str=scanner.nextLine();
System.out.println(sum2(str));//效率高啦,1秒内就出结果,效率高啊
// System.out.println(sum1(str));//1000以上效率就不行啦,过50%的用例
}
}
这个题目好长啊,我猜可能使用动态规划或贪心算法来做。目前这个题目我想了比较长的时间还不知道怎么做。一点思路都没有。估计这个题目放到最后,就是最难的,把我吓到啦。以后再写题解啦。
4月10号更新题解。
解析:这道题的题面较为复杂,但理清以后会发现,装备数其实没什么用,实质是把各种各样的珠子放进不同等级的孔里(珠子等级≤孔等级),同时每种珠子放进若干个会产生一个递增的价值,用一个数组描述,但放多少个有上限,比如上限为5,则放进6个和5个的价值相同。
这道题和背包问题很像,但有两点不同,第一点是高等级的珠子不能放进低等级的孔中,因此放入有限制;第二点是同种珠子放入不同的个数的价值是用一个数组描述的,而不是每个珠子是一样的价值。
由于一共只有4个等级,因此对于输入量,我们选择按照等级记录每个等级的孔数,还有每种珠子放若干个的价值。因为孔的等级对于珠子的等级是向下兼容的,因此选择从高等级到低等级逐层开放孔数,同时优先放同等级的珠子,放入时就不会受到限制,即可转换为背包问题,孔数即相当于容量。
以dp[i][j]表示前 i 种珠子放入 j 个孔中所能产生的最大价值,每开放一个等级就枚举与之等级相同的珠子放多少个,然后与前i - 1种珠子相对应转移过来的情况进行比较。
代码如下:
package com.lanqiao.十一届省赛第二场Java大学B组;
import java.util.Scanner;
//参考博客:https://blog.csdn.net/weixin_46270935/article/details/115093781
public class Class_10装饰珠 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int N;//每个装备的装饰孔的数量
int tmp;//孔的等级
int total=0;//所有等级孔的总数量
int[] hole=new int[5];//存放每个等级(1-4)的孔有多少,索引表示等级
for (int i = 0; i < hole.length; i++) {
hole[i]=0;
}
for (int i = 0; i < 6; i++) {
N=scanner.nextInt();
for (int j = 0; j < N; j++) {
tmp=scanner.nextInt();
hole[tmp]++;
total++;
}
}
int M=scanner.nextInt();//技能的种类
int[] level=new int[M+1];//第i种装饰珠的等级
int[][] w=new int[M+1][];//第i种装饰珠放j个的价值
for (int i = 1; i <= M; i++) {
level[i]=scanner.nextInt();
tmp=scanner.nextInt();
w[i]=new int[tmp+1];//代表一维数组,对于i不同,各一维数组可以不同。二维实质仍然是一维数组
for (int j = 1; j <= tmp; j++) {
w[i][j]=scanner.nextInt();//第i种装饰珠放j个的价值
}
}
//dp[i][j]表示前i种珠子放入j个孔中所能产生的最大价值,动态规划的核心数据结构
int[][] dp=new int[M+1][total+1];//M种技能(珠子),total种孔
int sum=0;
int kind=0;
for (int lev = 4; lev >=1 ; lev--) {
sum+=hole[lev];//该4等级开放的孔数,第二次循环4等级和三等级开放的孔数和
if (sum==0) {
continue;
}
for (int k = 1; k <= M; k++) {//第k种珠子
if (level[k]==lev) {//枚举该等级的珠子
kind++;
//必须先平行转移,因为有好几种情况(放i个)
for (int i = 1; i <= sum; i++) {
dp[kind][i]=dp[kind-1][i];//第kind种珠子未镶嵌
}
//放i个该种(第kind种)珠子
for (int i = 1; i < w[k].length; i++) {
for (int j = sum; j >= i; j--) {//j为孔数,最少为i
dp[kind][j]=Math.max(dp[kind][j], dp[kind-1][j-i]+w[k][i]);
}
}
}
}
}
System.out.println(dp[kind][sum]);//总共kind种珠子放入sum个孔里的最大价值。
}
}
测试用例:
5 1 1 1 1 1
9 1 1 1 1 1 1 1 1 1
7 1 1 1 1 1 1 1
3 1 1 1
7 1 1 1 1 1 1 1
9 1 1 1 1 1 1 1 1 1
15
4 3 48 86 129
3 1 3
1 7 45 84 109 154 175 206 233
1 2 35 42
1 6 7 52 67 116 131 156
1 1 32
3 4 12 15 61 82
1 7 5 36 85 88 124 139 163
1 7 29 32 69 101 150 197 210
1 6 9 50 73 102 141 158
3 2 9 44
1 3 1 39 86
1 2 35 78
1 7 3 50 53 96 107 140 175
3 6 16 63 74 89 92 140
1195
1 1
2 1 2
1 1
2 2 2
1 1
1 3
3
1 5 1 2 3 5 8
2 4 2 4 8 15
3 2 5 10
20
动态规划的模板题目,有一些变化,只不过题目很长,所以耐心一点读清题意。
————————————————
版权声明:本题为CSDN博主「Hey XIN」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_46270935/article/details/115093781