目录
1.门牌制作
2.寻找2020
3.蛇形填数
4.七段码
5.排序
6.成绩分析
7.单词分析
8.数字三角形
9.子串分值和
10.装饰珠
【问题描述】
小蓝要为一条街的住户制作门牌号。
这条街一共有 2020 位住户,门牌号从 1 到 2020 编号。
小蓝制作门牌的方法是先制作 0 到 9 这几个数字字符,最后根据需要将字符粘贴到门牌上,例如门牌 1017 需要依次粘贴字符 1、0、1、7,即需要 1 个字符 0,2 个字符 1,1 个字符 7。
请问要制作所有的 1 到 2020 号门牌,总共需要多少个字符 2?
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
编写程序打印出1~2020,复制到word文档上,在word文档里查找"2"。
public class Main {
public static void main(String[] args) {
for(int i = 1;i <= 2020;i++) {
System.out.println(i);
}
}
}
//暴搜,统计有多少个"2"
public class Main {
public static void main(String[] args) {
int sum = 0;
for(int i = 1;i <= 2020;i++) {
int g = i % 10;//个位数字
int s = i / 10 % 10;//十位数字
int b = i / 100 % 10;//百位数字
int q = i / 1000;//千位数字
if(g == 2)
sum++;
if(s == 2)
sum++;
if(b == 2)
sum++;
if(q == 2)
sum++;
}
System.out.println(sum);
}
}
public class Main {
public static void main(String[] args) {
int count = 0;
for(int i=1;i<=2020;i++){
int x =i;//定义一个变量x 替换i ,防止发生死循环
while(x>0){
if(x%10==2){//模10检查每一位是否为2,为2的话,计数器count+1
count++;
}
x=x/10;//x的位数减1,带入到下一次while循环中
}
}
System.out.println(count);//运行结果为624
}
}
public class Main {
public static void main(String[] args) {
int count=0;
for(int i=1;i<=2020;i++){
String string=String.valueOf(i);
if(string.contains("2")){
int n=string.length()-string.replaceAll("2","").length();
count=count+n;
}
}
System.out.println(count);
}
}
String string=String.valueOf(i); 将int变量i转换成字符串。
string.contains() 判断string中是否有子字符串,有则返回true,没有则返回false。
string.replaceAll() 替换字符串
public class Main {
static int sum=0;
public static void main(String[] args) {
for(int i=1;i<=2020;i++) {
String s=i+"";
for(int j=0;j
答案:624
【问题描述】
小蓝有一个数字矩阵,里面只包含数字 0 和 2。小蓝很喜欢 2020,他想找
到这个数字矩阵中有多少个 2020 。
小蓝只关注三种构成 2020 的方式:同一行里面连续四个字符从左到右构成 2020。
同一列里面连续四个字符从上到下构成 2020。
在一条从左上到右下的斜线上连续四个字符,从左上到右下构成 2020。
例如,对于下面的矩阵:
220000000000
002202
000000
000022
002020
一共有 5 个 2020。其中 1 个是在同一行里的,1 个是在同一列里的,3 个是斜线上的。
小蓝的矩阵比上面的矩阵要大,由于太大了,他只好将这个矩阵放在了一个文件里面,在试题目录下有一个文件 2020.txt,里面给出了小蓝的矩阵。
请帮助小蓝确定在他的矩阵中有多少个 2020。【答案提交】这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个
整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
import java.math.BigInteger;
import java.util.Scanner;
public class Main{
public static long count;
public static void main(String[] args) {
Scanner read = new Scanner(System.in);
String[] str = new String[300];
for(int i=0;i<300;i++)
{
str[i] = read.nextLine();
}
read.close();
f(str);
System.out.println(count);
read.close();
}
public static void f(String[] str)
{
for(int i=0;i=4 && str[i].charAt(j+1)=='0' && str[i].charAt(j+2)=='2' && str[i].charAt(j+3)=='0')
count++;
//竖向
if(str.length-i>=4 && str[i+1].charAt(j)=='0' && str[i+2].charAt(j)=='2' && str[i+3].charAt(j)=='0')
count++;
//斜向
if(str[i].length()-j>=4 && str.length-i>=4 && str[i+1].charAt(j+1)=='0' && str[i+2].charAt(j+2)=='2' && str[i+3].charAt(j+3)=='0')
count++;
}
}
}
}
}
import java.util.Scanner;
public class Main {
static int N = 100000 * 4 + 5;
static int M = 1000 + 5;
static int mod = 1000000009;
static Scanner cin = new Scanner(System.in);
static int ans = 0, n, m;
static char c[][] = new char[M][M];
public static void main(String[] args) {
int n1 =0;
while(cin.hasNext()) {
String s = cin.next();
if ("end".equals(s))
break;
m = s.length();
c[n++] = s.toCharArray();
}
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if (c[i][j]=='2')
check(i,j);
}
}
System.out.println(ans);
}
private static void check(int i, int j) {
if(i + 3 < n)
if(c[i+1][j] == '0' && c[i+2][j] == '2' && c[i+3][j] == '0')
++ans;
if(j + 3 < m)
if(c[i][j+1] == '0' && c[i][j+2] == '2' && c[i][j+3] == '0')
++ans;
if(i + 3 < n && j + 3 < n)
if(c[i+1][j+1] == '0' && c[i+2][j+2] == '2' && c[i+3][j+3] == '0')
++ans;
}
}
import java.util.Scanner;
public class Main {
public static int count(int x,int y,char[][] num) {
int count = 0;
if(y + 3 < 300)
if( num[y+1][x] == '0' && num[y+2][x] == '2' && num[y+3][x] == '0')
count++;
if(x + 3 < 300)
if( num[y][x+1] == '0' && num[y][x+2] == '2' && num[y][x+3] == '0')
count++;
if(y + 3 < 300 && x + 3 < 300)
if( num[y+1][x+1] == '0' && num[y+2][x+2] == '2' && num[y+3][x+3] == '0')
count++;
return count;
}
public static void main(String[] args){
Scanner in = new Scanner(System.in);
char[][]num = new char[300][300];
for (int i = 0; i < 300; i++) {
String string = in.next();
for (int j = 0; j < 300; j++) {
num[i][j] = string.charAt(j) ;
}
}
int count = 0;
for (int i = 0; i < 300; i++) {
for (int j = 0; j < 300; j++) {
count+=count(j, i, num);
}
}
System.out.println(count);
}
答案:16520
如下图所示,小明用从 1 开始的正整数“蛇形”填充无限大的矩阵。
容易看出矩阵第二行第二列中的数是 5。请你计算矩阵中第 20 行第 20 列 的数是多少?
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
只观察斜对角的数,仔细分析,(1,1)=1、(2,2)=5、(3,3)=13、......(20,20)=?
可以总结出公式:
public class Main{
public static void main(String[] args) {
int an = 1;
for(int i=1; i<=20; i++) {
an += 4*(i-1);
}
System.out.println(an);
}
}
答案:761
【问题描述】
小蓝要用七段码数码管来表示一种特殊的文字。
上图给出了七段码数码管的一个图示,数码管中一共有 7 段可以发光的二极管,分别标记为 a, b, c, d, e, f, g。小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符的表达时,要求所有发光的二极管是连成一片的。
例如:b 发光,其他二极管不发光可以用来表达一种字符。
例如:c 发光,其他二极管不发光可以用来表达一种字符。这种方案与上一行的方案可以用来表示不同的字符,尽管看上去比较相似。
例如:a, b, c, d, e 发光,f, g 不发光可以用来表达一种字符。
例如:b, f 发光,其他二极管不发光则不能用来表达一种字符,因为发光的二极管没有连成一片。
请问,小蓝可以用七段码数码管表达多少种不同的字符?
public class Main {
public static int N=10;
public static int e[][]=new int[N][N];//存储二极管相邻的信息
public static int f[]=new int[N];//并查集
public static int ans=0;
public static boolean st[]=new boolean[N];//true表示发光
public static void init(){
//表示相邻
//1 2 3 4 5 6 7
//a b c d e f g
e[1][2]=e[1][6]=1;//a与b、f相邻
e[2][1]=e[2][7]=e[2][3]=1;//b与a、g、c相邻
e[3][2]=e[3][7]=e[3][4]=1;//c与b、g、d相邻
e[4][3]=e[4][5]=1;//d与c、e相邻
e[5][7]=e[5][6]=e[5][4]=1;//e与g、f、d相邻
e[6][5]=e[6][7]=e[6][1]=1;//f与e、g、a相邻
e[7][2]=e[7][3]=e[7][5]=e[7][6]=1;//g与b、c、e相邻
}
public static int find(int u){
if(f[u]==u) return u;
f[u]=find(f[u]);
return f[u];
}
public static void dfs(int d){//1-7
if(d>7){
//终止条件
for(int i=1;i<=7;i++){//并查集初始化
f[i]=i;
}
for(int i=1;i<=7;i++){
for(int j=1;j<=7;j++){
if(e[i][j]==1&&st[i]==true&&st[j]==true){//把所有发光且相邻的二极管合并
int fx=find(i),fy=find(j);
if(fx!=fy){
f[fx]=fy;//合并
}
}
}
}
int k=0;//表示产生的集合的个数
for(int i=1;i<=7;i++){
if(st[i] &&f[i]==i)k++;
}
if(k==1) ans++;//只产生一个集合,说明所有的发光二极管是连成一片的
return;
}
st[d]=true;
dfs(d+1);
st[d]=false;
dfs(d+1);
}
public static void main(String[] args) {
init();
dfs(1);
System.out.println(ans);
}
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
public class Main{
static int counts=0;
static Setset=new HashSet<>();
static Map>map=new HashMap<>();
public static void main(String[] args) {
String str="abcdefg";
//初始化
ArrayListlist1=new ArrayList<>();
ArrayListlist2=new ArrayList<>();
ArrayListlist3=new ArrayList<>();
ArrayListlist4=new ArrayList<>();
ArrayListlist5=new ArrayList<>();
ArrayListlist6=new ArrayList<>();
ArrayListlist7=new ArrayList<>();
list1.add("b");list1.add("f");
list2.add("a");list2.add("g");list2.add("c");
list3.add("b");list3.add("g");list3.add("d");
list4.add("c");list4.add("e");
list5.add("f");list5.add("g");list5.add("d");
list6.add("a");list6.add("g");list6.add("e");
list7.add("f");list7.add("e");list7.add("b");list7.add("c");
map.put("a", list1);
map.put("b", list2);
map.put("c", list3);
map.put("d", list4);
map.put("e", list5);
map.put("f", list6);
map.put("g", list7);
//求字符串的所有字串
find("",str,0);
System.out.println(counts);
}
static void find(String temp,String str,int index) {
if(index==str.length()) {
//最后对得到的字串检查是否是一个连通区域
if(bfsCheck(temp.toCharArray()))counts++;
return;
}
find(temp,str,index+1);
find(temp+=str.charAt(index),str,index+1);
}
static boolean bfsCheck(char[] strs) {
//先对简单情形直接判断
if(strs.length==0)return false;
if(strs.length==1)return true;
if(strs.length==2) {
if(map.get(strs[0]+"").contains(strs[1]+""))return true;
else return false;
}
LinkedList queue=new LinkedList<>();
int connect=1;
queue.add(strs[0]+"");
strs[0]='0';
while(!queue.isEmpty()) {
String str = queue.poll();
ArrayList list = map.get(str);
for(int i=0;i
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
static int N = 100000 * 4 + 5;
static int M = 1000 + 5;
static int mod = 1000000009;
static Scanner cin = new Scanner(System.in);
static int ans = 0, n, m;
static ArrayList g[] = new ArrayList[N]; //建图 第i个数组的元素都跟i相连
static boolean vis[] = new boolean[N]; //判断当前这条线段是否被递归过
static boolean dp[] = new boolean[N]; //二进制判重
static int a[] = new int[1<<8];
public static void main(String[] args) {
for(int i = 1; i <= 7; i++)
g[i] = new ArrayList();
//这里就是赋予数字意义 重新连边
add(1, 2); add(1, 6); add(2, 7); add(2, 3); add(3, 4);
add(4, 5); add(5, 6); add(5, 7); add(6, 7); add(3, 7);
for(int i = 1; i <= 7; i++) {
vis[i] = true; //这里枚举是保证至少有一条灯管是亮着的
dfs(i , 1);
vis[i] = false;
}
System.out.println(ans);
}
private static void dfs(int u, int k) {
a[k] = u; //递归的第k条线段是数字编号为u的线段
check(k); //对每个状态都判重
//这里从1枚举到k就是枚举当前联通块相连的边
for(int i = 1; i <= k; i++) {
for(int v: g[a[i]]) {
if(vis[v]) continue;
vis[v] = true;
dfs(v, k + 1);
vis[v] = false;
}
}
}
private static void check(int k) {
int res = 0;
for(int i = 1; i <= k; i++) //因为每个线段的数字不同 代表的二进制数字也就不同
res += (1<
答案:80
【问题描述】
小蓝最近学习了一些排序算法,其中冒泡排序让他印象深刻。
在冒泡排序中,每次只能交换相邻的两个元素。
小蓝发现,如果对一个字符串中的字符排序,只允许交换相邻的两个字符, 则在所有可能的排序方案中,冒泡排序的总交换次数是最少的。
例如,对于字符串 lanlan 排序,只需要 11 次交换。对于字符串 qiaoqiao 排序,总共需要 44 次交换。
小蓝找到了很多字符串试图排序,他恰巧碰到一个字符串,需要 100100 次交 换,可是他忘了吧这个字符串记下来,现在找不到了。
请帮助小蓝找一个只包含小写英文字母且没有字母重复出现的字符串,对该串的字符排序,正好需要 100100 次交换。如果可能找到多个,请告诉小蓝最短的那个。如果最短的仍然有多个,请告诉小蓝字典序最小的那个。
【解析】I.随机找(本题的关键点:字典序的字符选取一定是先选最小的(从而保证了,最小的字典序)),通过冒泡法排序,找到第一次大于100的交换数量,确定字符串的长度,从右往左依次添加,(a),(b,.a)…从而能够找到这样一个序列char a[]={‘o’,‘n’,‘m’,‘l’,‘k’,‘j’,‘i’,‘h’,‘g’,‘f’,‘e’,‘d’,‘c’,‘b’,‘a’};通过冒泡得到交换105次,那所求的字典序一定是上面这些字符(经过字典序排序)得到。
II.再通过最小的字典序b[],找到下一个比刚好比b[]小的字典序,然后复制给a[],对a[]进行冒牌,返回交换的次数sum,循环直到sum为100结束,此时b[]就是我们所需要的字典序了。
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
char a[]={'o','n','m','l','k','j','i','h','g','f','e','d','c','b','a'};
for (int i = 0; i < a.length; i++) {
}
char b[]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o'};
while(tsort(a)!=100) {
int t=0,ab=Integer.MAX_VALUE;
for (int i = b.length-1; i-1>=0; i--) {
if(b[i]>b[i-1]) {
for (int j = b.length-1; j >=i; j--) {
if(Math.abs(b[i-1]-b[j])a[j]) {
char t=a[i];
a[i]=a[j];
a[j]=t;
sum++;
}
}
}
return sum;
}
}
答案:jonmlkihgfedcba
【问题描述】
小蓝给学生们组织了一场考试,卷面总分为 100 分,每个学生的得分都是
一个 0 到 100 的整数。
请计算这次考试的最高分、最低分和平均分。
【输入格式】
输入的第一行包含一个整数 n,表示考试人数。
接下来 n 行,每行包含一个 0 至 100 的整数,表示一个学生的得分。
【输出格式】
输出三行
第一行包含一个整数,表示最高分。
第二行包含一个整数,表示最低分。
第三行包含一个实数,四舍五入保留正好两位小数,表示平均分。【样例输入】
7
80
92
56
74
88
99
10【样例输出】
99
10
71.29
printf()方法:带格式描述的数据输出。该方法包含两个参数,第一个参数中给出输出格式的描述,第2个参数为输出数据,其中,输出格式描述字符串中需要安排与输出数据对应的格式符。
常用格式符包括:%d代表十进制数;%f代表浮点数;%e代表科学表示法的指数位数;%n代表换行符;%x代表十六进制数;%s代表字符串。
两位小数用浮点型float,输出用printf("%.2f")
String.format()字符串常规类型格式化的两种重载方式。
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] a = new int [n];
for(int i=0;i
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] res = new int[n];
// 将输入的成绩存入数组中
for (int i = 0; i < res.length; i++) {
res[i] = sc.nextInt();
}
// 对成绩数组进行排序
Arrays.sort(res);
System.out.println(res[n - 1]);// 数组最后一个元素就是最大值
System.out.println(res[0]);// 数组第一个元素就是最小值
// 平均值
double avg = 0;
for (int i = 0; i < res.length; i++) {
avg += res[i];
}
System.out.println(String.format("%.2f", avg / n));
}
}
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();//人数
int[]score=new int[n];//学生的得分
for(int i=0;imax)max=i;//最高分
if(i
【问题描述】
小蓝正在学习一门神奇的语言,这门语言中的单词都是由小写英文字母组成,有些单词很长,远远超过正常英文单词的长度。小蓝学了很长时间也记不住一些单词,他准备不再完全记忆这些单词,而是根据单词中哪个字母出现得最多来分辨单词。
现在,请你帮助小蓝,给了一个单词后,帮助他找到出现最多的字母和这个字母出现的次数。
【输入格式】
输入一行包含一个单词,单词只由小写英文字母组成。
【输出格式】
输出两行,第一行包含一个英文字母,表示单词中出现得最多的字母是哪个。如果有多个字母出现的次数相等,输出字典序最小的那个。
第二行包含一个整数,表示出现得最多的那个字母在单词中出现的次数。
【样例输入】
lanqiao
【样例输出】
a2
【样例输入】
longlonglongistoolong
【样例输出】
o6
【评测用例规模与约定】
对于所有的评测用例,输入的单词长度不超过 1000。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
int max = 0;
int index = 0;
String a = "abcdefghijklmnopqrstuvwxyz";
int b[] = new int[26];
for(int i = 0;imax){
max = b[j];
index = j;
}
}
System.out.println(a.substring(index,index+1));
System.out.println(max);
}
}
indexOf()方法可返回某个指定的字符串值在字符串中首次出现的位置。
charAt()方法返回指定索引位置的char值,索引范围为0~length()-1。
substring()的作用就是截取父字符串的某一部分。
上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。 对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。
路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。
【输入格式】
输入的第一行包含一个整数 N (1 < N ≤ 100),表示三角形的行数。下面的 N 行给出数字三角形。数字三角形上的数都是 0 至 100 之间的整数。【输出格式】
输出一个整数,表示答案。【样例输入】
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5【样例输出】
27
时间限制: 1.0s 内存限制: 512.0MB
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int i, j;
int[][] x = new int[n + 1][n + 1];
for (i = 0; i < n; i++)
for (j = 0; j <= i; j++)
x[i][j] = sc.nextInt();
int[][] sum = new int[n + 1][n + 1];//储存所求的较大的数
for (j = 0; j < n; j++)
sum[n - 1][j] = x[n - 1][j];// 先将最后一行排列在相应位置
for (i = n - 2; i >= 0; i--)
for (j = 0; j <= i; j++)
sum[i][j] = Math.max(sum[i + 1][j], sum[i + 1][j + 1])
+ x[i][j];// 上一行中的数选择下一行可以相加的两个数中较大的再加上这个数本身,逐行求解
System.out.println(sum[0][0]);
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class Main{
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
//ArrayList 里存放每一行,每一行的数据使用 List 装。
ArrayList> list = new ArrayList<>();
for(int i=0;i());
String[] col = br.readLine().split(" ");
for (int j=0;j<=i;j++) {
list.get(i).add(Integer.parseInt(col[j]));
}
}
int sum = cauculate(n-1, 0, list.get(0).get(0), 0, 0, list);
System.out.println(sum);
}
// n 代表层数,sort 代表从该层中取第几位的数,left 代表向左取,right 代表向右取,list 是数字三角形。
public static int cauculate(int n, int sort, int sum, int left, int right, ArrayList> list){
if (right + left == n){
if (Math.abs(right - left) > 1)
return 0;
else
return sum;
}
// 向右下
int rvalue = cauculate(n, sort + 1, sum + list.get(right + 1 + left).get(sort + 1), left, right + 1, list);
// 向左下
int lvalue = cauculate(n, sort, sum + list.get(right + left + 1).get(sort), left + 1, right, list);
return lvalue >= rvalue ? lvalue : rvalue;
}
【问题描述】
对于一个字符串 S ,我们定义 S 的分值 f (S ) 为 S 中出现的不同的字符个数。
例如 f (”aba”) = 2, f (”abc”) = 3, f (”aaa”) = 1。
现在给定一个字符串 S [0…n − 1](长度为 n),请你计算对于所有 S 的非空子串 S [i… j](0 ≤ i ≤ j < n), f (S [i… j]) 的和是多少。
【输入格式】
输入一行包含一个由小写字母组成的字符串 S 。
【输出格式】
输出一个整数表示答案。【样例输入】
ababc
【样例输出】
28
【样例说明】
子串 f值
a 1
ab 2
aba 2
abab 2
ababc 3
b 1
ba 2
bab 2
babc 3
a 1
ab 2
abc 3
b 1
bc 2
c 1【评测用例规模与约定】
对于 20% 的评测用例,1≤n≤10;
对于 40% 的评测用例,1≤n≤100;
对于 50% 的评测用例,1≤n≤1000;
对于 60% 的评测用例,1≤n≤10000;
对于所有评测用例,1≤n≤100000。
【解析】纵向递推,计算每个位置字符的贡献度,可以推出每个字符贡献度的公式为:前一次出现该字符的位置到当前位置的距离绝对值*当前位置到字符串结尾的距离+1
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s=scanner.nextLine();
int [] pre = new int[27];
long ans=0;
int len=s.length();
for (int i = 1; i <= s.length(); i++) {
char x=s.charAt(i-1);
ans+=(i-pre[x-'a'])*(len-i+1);
pre[x-'a']=i;
}
System.out.println(ans);
}
}
【问题描述】
在怪物猎人这一款游戏中,玩家可以通过给装备镶嵌不同的装饰珠来获取 相应的技能,以提升自己的战斗能力。
已知猎人身上一共有 6 件装备,每件装备可能有若干个装饰孔,每个装饰孔有各自的等级,可以镶嵌一颗小于等于自身等级的装饰珠 (也可以选择不镶嵌)。
装饰珠有 M 种,编号 1 至 M,分别对应 M种技能,第 i种装饰珠的等级为 Li,只能镶嵌在等级大于等于 Li的装饰孔中。对第 i 种技能来说,当装备相应技能的装饰珠数量达到 Ki个时,会产生 Wi(Ki) 的价值。镶嵌同类技能的数量越多,产生的价值越大,即 Wi(Ki − 1) < Wi(Ki),但每个技能都有上限 Pi ( 1 ≤ Pi ≤ 7 )当装备的珠子数量超过 Pi时,只会产生 Wi(Pi) 的价值。对于给定的装备和装饰珠数据,求解如何镶嵌装饰珠,使得 6 件装备能得到的总价值达到最大。
【输入格式】
输入的第 1 至 6 行,包含 6 件装备的描述。其中第 i 的第一个整数 Ni表示第 i 件装备的装饰孔数量。后面紧接着 Ni 个整数,分别表示该装备上每个装饰孔的等级 Li ( 1 ≤ Li ≤ 4 )。第 7 行包含一个正整数 M,表示装饰珠 (技能) 种类数量。第 8 至 M + 7 行,每行描述一种装饰珠 (技能) 的情况。每行的前两个整数 Lj ( 1 ≤ Lj ≤ 4 ) 和 Pi ( 1 ≤ Pi ≤ 7 ) 分别表示第 jj种装饰珠的等级和上限。接下来 Pj个整数,其中第 k个数表示装备该中装饰珠数量为 k 时的价值 Wj(k)。
其中:1≤Ni≤50,1≤M≤10 ^4,1≤Wi≤10 ^4
【输出格式】
输出一行包含一个整数,表示能够得到的最大价值。
【样例输入】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【样例说明
按照如下方式镶嵌珠子得到最大价值 18,括号内表示镶嵌的装饰珠的种类编号:
1: (1)
2: (1) (2)
3: (1)
4: (2) (2)
5: (1)
6: (2)4 颗技能 1 装饰珠,4 颗技能 2 装饰珠 W1(4) + W2(4) = 5 + 15 = 20。W1(4)+W2(4)=5+15=20。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
while(sc.hasNext()) {
int lv1[]=new int[52],num[]=new int[7];
int t=0;
for (int i = 1; i < 7; i++) {
int t1=sc.nextInt();
num[i]=t1;
for (int j = 1; j <=t1; j++) {
lv1[++t]=sc.nextInt();
}
}
int m=sc.nextInt();
int lv2[]=new int[m+1],dp[][]=new int[m+1][t+1],lim[]=new int[m+1];
int w[][]=new int[m+1][8];
for (int i = 1; i <=m; i++) {
int t1=sc.nextInt();
lv2[i]=t1;
t1=sc.nextInt();
lim[i]=t1;
for (int j = 1; j <=t1; j++) {
w[i][j]=sc.nextInt();
}
}
Arrays.sort(lv1,1,t+1);
for (int i = 1; i <=m; i++) {
int t2=0,s=0;
for (int j = 1; j <=t; j++) {
if(lv1[j]>=lv2[i]) {
t2++;
if(t2==1) s=j-1;
int maxlim=t2>lim[i]?w[i][lim[i]]:w[i][t2];
dp[i][j]=Math.max(dp[i-1][j],dp[i][s]+maxlim);
}else {
dp[i][j]=dp[i-1][j];
}
}
}
int max=0;
for (int i = 1; i <=t; i++) {
if(dp[m][i]>max) max=dp[m][i];
}
System.out.println(max);
}
}
}