美团2019编程汇总

1、
给定一张包含N个点、N-1条边的无向连通图,节点从1到N编号,每条边的长度均为1。假设你从1号节点出发并打算遍历所有节点,那么总路程至少是多少?
输入描述:
第一行包含一个整数N,1≤N≤10^5。
接下来N-1行,每行包含两个整数X和Y,表示X号节点和Y号节点之间有一条边,1≤X,Y≤N。
输出描述:
输出总路程的最小值。
示例1
输入
4
1 2
1 3
3 4
输出
4
解析:这首先不是一个环,如果要想路径最短那么只能最长路径走一遍,短的路径走两遍(要返回1)。

import java.util.ArrayList;
import java.util.Scanner;
import java.util.Stack;

public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        ArrayList[] arr=new ArrayList[n+1];//邻接表
        for(int i=0;i<n;i++){
            int x=sc.nextInt();
            int y=sc.nextInt();
            arr[x].add(y);
            arr[y].add(x);
        }
        int len=0;
        Stack<Integer> stack=new Stack<>();
        stack.add(1);
        int[] visited=new int[n+1];
        visited[1]=1;
        //广度优先搜索
        while(!stack.isEmpty()){
            len++;
            Stack<Integer> s=new Stack<>();
            while(!stack.isEmpty()){
                int now=stack.pop();
                ArrayList<Integer> list=arr[now];
                for(Integer a:list){
                    if(visited[a]==0){
                        s.add(a);
                        visited[a]=1;
                    }
                }
            }
            stack=s;

        }
        System.out.println(2*(n-1)-len+1);
    }
}

2、
给你一个01字符串,定义答案=该串中最长的连续1的长度,现在你有至多K次机会,每次机会可以将串中的某个0改成1,现在问最大的可能答案
输入描述:
输入第一行两个整数N,K,表示字符串长度和机会次数
第二行输入N个整数,表示该字符串的元素
( 1 <= N <= 300000
, 0 <= K <= N )
输出描述:
输出一行表示答案
输入例子1:
10 2
1 0 0 1 0 1 0 1 0 1
输出例子1:
5
解析:滑动窗口,找出连续的最大值。一直滑动右窗口,如果0的值超过k,再滑动左窗口。

import java.util.Scanner;

public class Main2 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int k=sc.nextInt();
        int[] num=new int[n];
        for(int i=0;i<n;i++){
            num[i]=sc.nextInt();
        }
        int left=0,right=0;
        int count=0;
        int max=Integer.MIN_VALUE;
        while(right<n){
            if(num[right]==0) count++;
            while(count>k){
                if(num[left]==0) count--;
                left++;
            }
            max=Math.max(max,right-left+1);
            right++;
        }
        System.out.println(max);
    }
}

3、你打开了美了么外卖,选择了一家店,你手里有一张满X元减10元的券,店里总共有n种菜,第i种菜一份需要A_i元,因为你不想吃太多份同一种菜,所以每种菜你最多只能点一份,现在问你最少需要选择多少元的商品才能使用这张券。
输入描述:
第一行两个正整数n和X,分别表示菜品数量和券的最低使用价格。(1≤n≤100, 1≤X≤10000) 接下来一行n个整数,第i个整数表示第i种菜品的价格。(1≤A_i≤100)
输出描述:
一个数,表示最少需要选择多少元的菜才能使用这张满X元减10元的券,保证有解。
输入例子1:
5 20
18 19 17 6 7
输出例子1:
23
解析:
01背包,动态规划,dp[x+1],定义未达到i元的最低消费,剩下j元,对于当前物品int[i],价值和花费为int[i],是否购买当前物品分两种情况:
当前价值j不够或者刚好能够购买物品i,买了物品i不能买其他物品了,dp[j]是前i-1件的最小价值,与当前价值作比较;
当前价值j超过了物品i的价值,买了物品i,还能买其他物品。

import java.util.Arrays;
import java.util.Scanner;

public class Main3 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int x=sc.nextInt();
        int[] arr=new int[n];
        for(int i=0;i<arr.length;i++){
            arr[i]=sc.nextInt();
        }
        //dp[i]表示达到i元的最低消费
        int[] dp=new int[x+1];
        dp[0]=0;
        Arrays.fill(dp,100001);
        for(int i=0;i<n;i++){
            for(int j=x;j>=0;j--){
                if(j>arr[i]){
                    dp[j]=Math.min(dp[j],dp[j-arr[i]]+arr[i]);
                }else{
                    dp[j]=Math.min(dp[j],arr[i]);
                }
            }
        }
        System.out.println(dp[x]);
    }
}

4、
公园里有N个花园,初始时每个花园里都没有种花,园丁将花园从1到N编号并计划在编号为i的花园里恰好种A_i朵花,他每天会选择一个区间[L,R](1≤L≤R≤N)并在编号为L到R的花园里各种一朵花,那么园丁至少要花多少天才能完成计划?
输入描述:
第一行包含一个整数N,1≤N≤10^5。
第二行包含N个空格隔开的整数A_1到A_N,0≤A_i≤10^4。
输出描述:
输出完成计划所需的最少天数。
示例1
输入
5
4 1 8 2 5
输出
14
解析:例如 4 1 8 2 5
因为最小的肯定会先变为0,如果让所有的值都先变为最小值,即可一起变为0
遍历,如果前者的值大于后者,就取差值,这个差值n表明经过n天,这两个花园的花一样。
即4 1 8 2 5 -经过3天> 1 1 8 2 5 -经过6天> 1 1 2 2 5 ->再经过5天就都为0了。

import java.util.Scanner;

public class Main4 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int[] num=new int[n];
        for(int i=0;i<n;i++){
            num[i]=sc.nextInt();
        }
        int res=0;
        for(int i=1;i<n;i++){
            if(num[i-1]>num[i]){
                res+=num[i-1]-num[i];
            }
        }
        res+=num[n-1];
        System.out.println(res);
    }
}

5、
小明同学在参加一场考试,考试时间2个小时。试卷上一共有n道题目,小明要在规定时间内,完成一定数量的题目。 考试中不限制试题作答顺序,对于 i 第道题目,小明有三种不同的策略可以选择: (1)直接跳过这道题目,不花费时间,本题得0分。 (2)只做一部分题目,花费pi分钟的时间,本题可以得到ai分。 (3)做完整个题目,花费qi分钟的时间,本题可以得到bi分。 小明想知道,他最多能得到多少分。
输入描述:
第一行输入一个n数表示题目的数量。
接下来n行,每行四个数p_i,a_i,q_i,b_i。(1≤n≤100,1≤p_i≤q_i≤120,0≤a_i≤b_i≤1000
)。
输出描述:
输出一个数,小明的最高得分。
示例1
输入
4
20 20 100 60
50 30 80 55
100 60 110 88
5 3 10 6
输出
94
解析:0-1背包问题,使用一维动态规划,dp[i]表示在花费i时间得分的值。

import java.util.Scanner;

public class Main5 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int[][] num=new int[n][4];
        for(int i=0;i<n;i++){
            for(int j=0;j<4;j++){
                num[i][j]=sc.nextInt();
            }
        }
        int[] dp=new int[121];
        for(int i=0;i<n;i++){
            for(int j=120;j>=0;j--){
                if(num[i][0]<=j){
                    dp[j]=Math.max(dp[j],dp[j-num[i][0]]+num[i][1]);
                }
                if(num[i][2]<=j){
                    dp[j]=Math.max(dp[j],dp[j-num[i][2]]+num[i][3]);
                }
            }
        }
        System.out.println(dp[120]);
    }
}

6、
一条直线上等距离放置了n台路由器。路由器自左向右从1到n编号。第i台路由器到第j台路由器的距离为| i-j |。 每台路由器都有自己的信号强度,第i台路由器的信号强度为ai。所有与第i台路由器距离不超过ai的路由器可以收到第i台路由器的信号(注意,每台路由器都能收到自己的信号)。问一共有多少台路由器可以收到至少k台不同路由器的信号。
输入描述:
输入第一行两个数n , k(1≤n , k≤10^5)
第二行n个数, a1 , a2 , a3……… , an(0≤ai≤10^9)
输出描述:
输出一个数,一共有多少台路由器可以收到至少k台不同路由器的信号。
示例1
输入
4 4
3 3 3 3
输出
4
解析:使用差分数组,思想是,如果是3路由器在发出信号,如果1能得到信号,那么2也能,如果5不能得到信号,那么6也不能。所以,可以利用差分的思想,当面路由的信号都是可以累加前面的路由器的信号的。(为什么可以累加前面的,因为如果1可以得到,2也可以,但是在进行统计的时候,只统计到边界,也就是最左边可以到1,那么统计2的时候是可以到1的+正好边界可以照到2的)。

import java.util.Scanner;

public class Main6 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int k=sc.nextInt();
        int[] router=new int[n];//这个就是差分数组
        for(int i=0;i<n;i++){
            int num=sc.nextInt();
            int start=Math.max(0,i-num);
            router[start]++;
            if(num+i+1<n){
                router[num+i+1]--;
            }
        }
        int ans=0;
        int sum=0;
        for(int i=0;i<n;i++){
            sum+=router[i];
            if(sum>=k){
                ans++;
            }
        }
        System.out.println(ans);
    }
}

7、
在D塔2这款游戏中,英雄和小兵都可以对对方的防御塔造成伤害,但是只有当对敌方防御塔最后的伤害是由英雄造成时,才会得到相应的金钱奖励。 现在小明正在玩D塔2,操作英雄带着一波兵进入了对方的塔下进行攻击。已知: 1. 一共有n个小兵,小兵的攻击力为d,所有小兵对塔的攻击是同时进行的,小兵的攻击冷却为t0。 2. 小明的英雄有一个技能可以对塔造成伤害,伤害值为x;英雄的普通攻击也可以对塔造成的伤害,伤害值为y。小明的英雄普通攻击的冷却为t1,技能冷却为t2。 3. 小兵的攻击,小明的普通攻击和小明的技能攻击,只要冷却时间一到,就会马上攻击;小明的普通攻击和技能攻击可以同时施展;如果小兵和英雄同时攻击,小兵的伤害算在前。 已知现在对方的塔还剩下s的血量,所有小兵的第一次攻击和英雄的第一次普通攻击和技能攻击在初始时刻同时进行,问小明可以得到破坏该塔的金钱奖励么? 注意:这里冷却是指连续两次攻击之间的等待时间,英雄的普通攻击和技能攻击的冷却两者互不干预。如果冷却是1,某次攻击发生在时间2,那么时间3才可以继续攻击。假定攻击立即生效。
输入描述:
第一行一个整数T,表示测试组数,1≤T≤10;
接下来一行一个整数s,表示塔的剩余血量,1≤s≤10000;
接下来一行4个整数n,d,x,y,含义如题面,1≤n,d,x,y≤100;
接下来一行3个整数t0,t1,t2,含义如题面,1≤t0,t1,t2≤100。
输出描述:
对于每组测试数据输出”YES”表示小明的英雄可以补到,”NO”表示不能。(输出不包括引号)

import java.util.Scanner;

public class Main7 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int T=sc.nextInt();
        for(int i=0;i<T;i++){
            int s = sc.nextInt();
            int n = sc.nextInt();
            int d = sc.nextInt();
            int x = sc.nextInt();
            int y = sc.nextInt();
            int t0 = sc.nextInt();
            int t1 = sc.nextInt();
            int t2 = sc.nextInt();
            int j=0;//用来计时
            while(true){
                if(j%t0==0){
                    s-=n*d;
                    if(s<=0){
                        System.out.println("NO");
                        break;
                    }
                }
                if(j%t1==0) s-=y;
                if(j%t2==0) s-=x;
                if(s<=0){
                    System.out.println("YES");
                    break;
                }
                j++;
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值