第一题:
有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n 个学生中按照顺序选取 k 名学生,要求相邻两个学生的位置编号的差不超过 d,使得这 k 个学生的能力值的乘积最大,你能返回最大的乘积吗?
输入描述:
每个输入包含1哥测试用例。每个测试数据的第一行包含一个证书n(1<=n<=50),表示学生的个数,接下来的一行,包含n个整数,按顺序表示表示学生的能力值ai(-50<=ai<=50)。接下来的一行包含两个整数,k和d(1<=k<=10, 1<=d<=50)。
输出描述:
输出的一行表示最大的乘积。
import java.util.*;
public class Main {
public static void main(String args[]){
Scanner s=new Scanner(System.in);
int n=s.nextInt();
int val[]=new int[n+1];
int i,j;
for(i=1;i<=n;i++)
val[i]=s.nextInt();
int k,d;
k=s.nextInt();
d=s.nextInt();
long mx[][]=new long[n+1][k+1];
long mn[][]=new long[n+1][k+1];
for(i=1;i<=n;i++){
mx[i][1]=mn[i][1]=val[i];
}
for(i=2;i<=n;i++){
for(j=2;j<=k&&i>=j;j++){
int h;
long max=Integer.MIN_VALUE;
long min=Integer.MAX_VALUE;
for(h=i-1;h>=i-d&&h>=1&&h>=j-1;h--){
if(max<mx[h][j-1])
max=mx[h][j-1];
if(min>mn[h][j-1])
min=mn[h][j-1];
}
if(val[i]>0){
mx[i][j]=val[i]*max;
mn[i][j]=val[i]*min;
}else{
mx[i][j]=val[i]*min;
mn[i][j]=val[i]*max;
}
}
}
long max=Integer.MIN_VALUE;
for(i=n;i>=k;i--)
if(max<mx[i][k])
max=mx[i][k];
System.out.println(max);
}
}
第二题:
给定一个 n 行 m 列的地牢,其中 '.' 表示可以通行的位置,'X' 表示不可通行的障碍,牛牛从 (x0 , y0 ) 位置出发,遍历这个地牢,和一般的游戏所不同的是,他每一步只能按照一些指定的步长遍历地牢,要求每一步都不可以超过地牢的边界,也不能到达障碍上。地牢的出口可能在任意某个可以通行的位置上。牛牛想知道最坏情况下,他需要多少步才可以离开这个地牢。
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int n = scanner.nextInt();
int m = scanner.nextInt();
char[][] map = new char[n][m];
for (int i = 0; i < n; i++) {
String s = scanner.next();
map[i] = s.toCharArray();
}
int x0 = scanner.nextInt();
int y0 = scanner.nextInt();
int k = scanner.nextInt();
int[][] move = new int[k][2];
for(int i=0;i<k;i++){
move[i][0] = scanner.nextInt();
move[i][1] = scanner.nextInt();
}
System.out.println(maxStep(n, m, map, x0, y0, k, move));
}
}
public static int maxStep(int n, int m, char[][] map, int x0, int y0, int k, int[][] move) {
int[][] dis = new int[n][m];// 访问标记
//引入队列是为了遍历到没有出路为止 总结:广度遍历一般都需要队列。
Queue<Integer> queueX = new LinkedList<Integer>();
Queue<Integer> queueY = new LinkedList<Integer>();
queueX.add(x0); // 添加起始位置
queueY.add(y0);
dis[x0][y0] = 1;
while (!queueX.isEmpty() && !queueY.isEmpty()) {
x0 = queueX.remove();
y0 = queueY.remove();
for (int i = 0; i < k; i++) {
//保证不出界
if (x0 + move[i][0] >= 0 && x0 + move[i][0] < n && y0 + move[i][1] >= 0 && y0 + move[i][1] < m) {
if(dis[x0 + move[i][0]][y0 + move[i][1]] == 0){
if(map[x0 + move[i][0]][y0 + move[i][1]] == '.'){
queueX.add(x0 + move[i][0]);
queueY.add(y0 + move[i][1]);
dis[x0 + move[i][0]][y0 + move[i][1]] = dis[x0][y0] + 1;
}
else{
dis[x0 + move[i][0]][y0 + move[i][1]] = -1;
}
}
}
}
}
int maxStep = Integer.MIN_VALUE;
int hasRoad = 1;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(dis[i][j] == 0 && map[i][j] == '.'){
hasRoad = 0; //存在没有被访问的“.”说明路径不能遍历完全,有些出口到不了。
}
maxStep = Math.max(dis[i][j], maxStep);
}
}
if(hasRoad == 0){
return -1;
}
else{
return maxStep - 1; // 因为起始步的dis值为1,这里要减去1.
}
}
}
第三题:
牛牛想尝试一些新的料理,每个料理需要一些不同的材料,问完成所有的料理需要准备多少种不同的材料。
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class Main {
public static Scanner sc = new Scanner(System.in);
public static void main(String... args){
int res = test06();
System.out.println(res);
}
public static int test01() {
int len = sc.nextInt();
int[] inputs = new int[len];
for(int i=0; i<len; i++){
inputs[i] = sc.nextInt();
}
int start =0;
int end = len-1;
int times = 0;
while(start<=end){
if(inputs[start]<inputs[end]){
inputs[++start]+=inputs[start-1];
times++;
}else if(inputs[start]>inputs[end]){
inputs[end--]+=inputs[end+1];
times++;
}else{
start++;
end--;
}
}
return times;
}
public static int test02(){
int res = 0;
int input = sc.nextInt();
double r = Math.sqrt(input);
if(r%1==0){
res = 4;
}
for(int i=0;i<r;i++){
for(int j=0;j<r;j++){
if(Math.pow(i, 2)+Math.pow(j, 2) == input){
res+=4;
}
}
}
return res;
}
public static int test03(){
int res = 0;
int k = sc.nextInt();
int m = sc.nextInt();
int[] minres = new int[m+1];
for(int i=0;i<m+1;i++){
minres[i] = 99999;
}
aa(k,m,minres,res);
return minres[0];
}
public static int test04(){
int res = -1;
int n = sc.nextInt();
int[] minres = new int[n+1];
for(int i=0;i<n+1;i++){
minres[i] = 9999;
}
minres[0] = 0;
for(int i=0;i<n;i++){
if(i+6<=n){
minres[i+6] = Math.min(minres[i+6], minres[i]+1);
}
if(i+8<=n){
minres[i+8] = Math.min(minres[i+8], minres[i]+1);
}
}
if(minres[n]==9999){
res = -1;
}else{
res = minres[n];
}
return res;
}
public static int test05(){
int res = -1;
int n =sc.nextInt();
int[] skills = new int[n];
for(int i=0;i<n;i++){
skills[i] = sc.nextInt();
}
int k = sc.nextInt();
int d = sc.nextInt();
int[] maxsk = new int[n+1];
int[] ks = new int[n+1];
for(int i=0;i<n+1;i++){
maxsk[i] = 0;
ks[i] = 0;
}
for(int i=0;i<n+1;i++){
for(int j=1;j<=d;j++){
int tmp = i+j;
if(tmp<n){
if(maxsk[tmp]>skills[i]*skills[tmp]){
}else{
ks[tmp] = ks[tmp]+1;
maxsk[tmp] = skills[i]*skills[tmp];
}
}
}
}
res = maxsk[n];
return res;
}
public static int test06(){
int res = 0;
Set<String> sets =new HashSet<String>();
while(sc.hasNext()){
sets.add(sc.next());
}
res = sets.size();
return res;
}
private static void aa(int k,int m,int[] minres,int res){
ArrayList yues = getYue(k);
if(k<m){
for(int i=0;i<yues.size();i++){
int k2 = k+(Integer)yues.get(i);
minres[k2] = Math.min(minres[k2], ++res);
aa(k2,m,minres,res);
res--;
}
}else if(k==m){
if(--res<minres[0]){
minres[0] = res;
}
return;
}
return;
}
private static ArrayList getYue(int num){
ArrayList arr = new ArrayList();
for(int i=(int) (Math.sqrt(num)+1);i>1;i--){
if(num%i==0){
arr.add(i);
}
}
return arr;
}
}
第四题:
牛牛和 15 个朋友来玩打土豪分田地的游戏,牛牛决定让你来分田地,地主的田地可以看成是一个矩形,每个位置有一个价值。分割田地的方法是横竖各切三刀,分成 16 份,作为领导干部,牛牛总是会选择其中总价值最小的一份田地, 作为牛牛最好的朋友,你希望牛牛取得的田地的价值和尽可能大,你知道这个值最大可以是多少吗?
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner scan=new Scanner(System.in);
while(scan.hasNext()){
int n=scan.nextInt();
int m=scan.nextInt();
int[][] matrix=new int[n+1][m+1];
int[][] sum=new int[n+1][m+1];
for(int i=1;i<=n;i++){
String line=scan.next();
for(int j=1;j<=m;j++){
matrix[i][j]=line.charAt(j-1)-'0';
}
}
get_sum(matrix,sum);
int ans=binarySearch(sum);
System.out.println(ans);
}
}
public static int binarySearch(int[][] sum){
int l=0, r=sum[sum.length-1][sum[0].length-1]+1;
int ret=0, mid=0;
while(l<r){
mid=(l+r)>>1;
if(isLeagle(mid,sum)){
l=mid+1;
ret=mid;
}else{
r=mid;
}
}
return ret;
}
public static void get_sum(int[][] matrix, int[][] sum){
for(int i=1;i<matrix.length;i++){
for(int j=1;j<matrix[0].length;j++){
sum[i][j]=sum[i][j-1]+sum[i-1][j]+matrix[i][j]-sum[i-1][j-1];
}
}
}
public static int get_aera(int[][] sum, int x1, int y1, int x2, int y2){
return sum[x2][y2]-sum[x1][y2]-sum[x2][y1]+sum[x1][y1];
}
public static boolean isLeagle(int val, int[][] sum){
int n=sum.length-1;
int m=sum[0].length-1;
for(int j1=1;j1<=m-3;j1++)
for(int j2=j1+1;j2<=m-2;j2++)
for(int j3=j2+1;j3<=m-1;j3++){
int pre=0, cnt=0;
for(int i=1;i<=n;i++){
int a1=get_aera(sum,pre,0,i,j1);
int a2=get_aera(sum,pre,j1,i,j2);
int a3=get_aera(sum,pre,j2,i,j3);
int a4=get_aera(sum,pre,j3,i,m);
if(a1>=val&&a2>=val&&a3>=val&&a4>=val){
pre=i;
cnt++;
}
if(cnt>=4) return true;
}
}
return false;
}
}
第五题:
n 只奶牛坐在一排,每个奶牛拥有 ai 个苹果,现在你要在它们之间转移苹果,使得最后所有奶牛拥有的苹果数都相同,每一次,你只能从一只奶牛身上拿走恰好两个苹果到另一个奶牛上,问最少需要移动多少次可以平分苹果,如果方案不存在输出 -1。
import java.util.*;
public class Main {
public static void main(String args[]){
Scanner s=new Scanner(System.in);
int n=s.nextInt();
int i,j,a[]=new int[n];
for(i=0;i<n;i++)
a[i]=s.nextInt();
int sum=0;
for(i=0;i<n;i++)
sum+=a[i];
if(sum%n!=0){
System.out.println(-1);
return;
}
int avg=sum/n;
for(i=0;i<n;i++)
a[i]=a[i]-avg;
int num=0;
for(i=0;i<n;i++)
if(a[i]%2!=0){
System.out.println(-1);
return;
}else{
if(a[i]>0)
num+=a[i]/2;
}
System.out.println(num);
}
}
第六题:
航天飞行器是一项复杂而又精密的仪器,飞行器的损耗主要集中在发射和降落的过程,科学家根据实验数据估计,如果在发射过程中,产生了 x程度的损耗,那么在降落的过程中就会产生 x2 程度的损耗,如果飞船的总损耗超过了它的耐久度,飞行器就会爆炸坠毁。问一艘耐久度为 h 的飞行器,假设在飞行过程中不产生损耗,那么为了保证其可以安全的到达目的地,只考虑整数解,至多发射过程中可以承受多少程度的损耗?
import java.util.*;
import java.math.*;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scan=new Scanner(System.in);
long n=scan.nextLong();
long s=(long)Math.sqrt(n);
if(s*(s+1)>n)
System.out.println(s-1);
else
System.out.println(s);
}
}
第七题:
牛牛拿到了一个藏宝图,顺着藏宝图的指示,牛牛发现了一个藏宝盒,藏宝盒上有一个机关,机关每次会显示两个字符串 s 和t,根据古老的传说,牛牛需要每次都回答 t 是否是 s 的子序列。注意,子序列不要求在原字符串中是连续的,例如串 abc,它的子序列就有{空串, a, b, c, ab, ac, bc, abc} 8 种。
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNext()){
String s1 = in.next();
String s2 = in.next();
int i = 0,j = 0;
while( i<s1.length() && j<s2.length() ){
if(s1.charAt(i) == s2.charAt(j)){
i++;j++;
} else {
i++;
}
}
if(j == s2.length() ){
System.out.println("Yes");
} else {
System.out.println("No");
}
}
in.close();
}
}
第八题:
牛牛的作业薄上有一个长度为 n 的排列 A,这个排列包含了从1到n的n个数,但是因为一些原因,其中有一些位置(不超过 10个)看不清了,但是牛牛记得这个数列顺序对的数量是 k,顺序对是指满足 i < j 且 A[i] < A[j] 的对数,请帮助牛牛计算出,符合这个要求的合法排列的数目。
import java.util.*;
public class Main{
private static int n,k, missNum;
private static int[] arr=new int[100];
private static boolean[] exist=new boolean[101];
private static int[][] leftCnt=new int[100][10];
private static int[][] rightCnt=new int[100][10];
private static int[] tofill=new int[10];
public static void main(String[] args){
Scanner scan=new Scanner(System.in);
while(scan.hasNext()){
Arrays.fill(exist,false);
Arrays.fill(arr,0);
Arrays.fill(tofill,0);
for(int i=0;i<100;i++){
Arrays.fill(leftCnt[i],0);
Arrays.fill(rightCnt[i],0);
}
missNum=0;
n=scan.nextInt();
k=scan.nextInt();
for(int i=0;i<n;i++){
arr[i]=scan.nextInt();
if(arr[i]!=0)
exist[arr[i]]=true;
}
int index=0;
for(int i=1;i<=n;i++){
if(!exist[i]){
tofill[index++]=i;
missNum++;
}
}
int ans=solve();
System.out.println(ans);
}
}
public static int get_pair(int[] tofill){
int length=missNum;
int ret=0;
for(int i=0;i<length-1;i++)
for(int j=i+1;j<length;j++)
if(tofill[i]<tofill[j])
ret++;
return ret;
}
public static void swap(int[] arr, int i, int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
public static int factor(){
int ret=1;
for(int i=1;i<=missNum;i++)
ret*=i;
return ret;
}
public static void next_permutation(int[] tofill){
int length=missNum;
int index=length-2;
while(index>=0&&tofill[index]>tofill[index+1])
index--;
if(index<0){
int i=0,j=length-1;
while(i<j)
swap(tofill,i++,j--);
return;
}
int index2=index+1;
while(index2<length&&tofill[index2]>tofill[index])
index2++;
index2--;
swap(tofill,index,index2);
index++;
index2=missNum-1;
while(index<index2){
swap(tofill,index,index2);
index++;
index2--;
}
return;
}
public static int solve(){
int cnt1=0;
for(int i=0;i<n-1;i++)
for(int j=i+1;j<n;j++){
if(arr[i]==0) continue;
if(arr[i]<arr[j]) cnt1++;
}
for(int i=0;i<missNum;i++){
int cnt=0,index=0;
for(int j=0;j<n;j++){
if(arr[j]!=0){
if(arr[j]<tofill[i]) cnt++;
}else
leftCnt[tofill[i]][index++]=cnt;
}
}
for(int i=0;i<missNum;i++){
int cnt=0, index=missNum-1;
for(int j=n-1;j>=0;j--){
if(arr[j]!=0){
if(arr[j]>tofill[i]) cnt++;
}else
rightCnt[tofill[i]][index--]=cnt;
}
}
int ans=0;
int times=0;
int limit=factor();
do{
int cnt2=get_pair(tofill);
int cnt=cnt1+cnt2;
for(int i=0;i<missNum;i++)
cnt+=leftCnt[tofill[i]][i]+rightCnt[tofill[i]][i];
if(cnt==k) ans++;
times++;
next_permutation(tofill);
}while(times<limit);
return ans;
}
}