牛客.取金币力扣.四个选项牛客.接雨水牛客.加减

发布于:2025-09-05 ⋅ 阅读:(13) ⋅ 点赞:(0)

目录

 

牛客.取金币

力扣.四个选项

牛客.接雨水

牛客.加减


 

牛客.取金币

区间dp

找到重复子问题:找出整个数组能得到的最大积分,当拿走一个数字的时候,假如知道左边区域拿走金币的最大积分,右边区域拿走的最大积分,那么再加上中间这个数,拿走之后,不就是最大的积分

dp[i][j] :区间[i,j]的金币都拿走,能获得的最大积分是多少

最终结果

dp[0][n-1]

状态转移方程

此时会面对临界情况

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param coins int整型一维数组 
     * @return int整型
     */
    public int getCoins (ArrayList<Integer> coins) {
      int n=coins.size();
      int[]a=new int[n+2];
      for(int i=1;i<=n;i++){
        a[i]=coins.get(i-1);
      }
      a[0]=1;
      a[n+1]=1;
      int[][]dp=new int[n+2][n+2];
      for(int i=n;i>=1;i--){
        for(int j=1;j<=n;j++){
            for(int k=i;k<=j;k++){
         dp[i][j]=Math.max(dp[i][k-1]+dp[k+1][j]+a[i-1]*a[k]*a[j+1],dp[i][j]);
            }
        }
      }
      return dp[1][n];
    }
}

力扣.四个选项

没怎么想明白,以为可以比如C3^12,C3^9,C3^6,然后就不咋不会写了,发现她这个是一个一个枚举,但是那我也没会写,没理解他的意思是啥,就写不出来

import java.util.*;
public class Main{
    static boolean[][]same=new boolean[13][13];
    static int ret=0;
    //记录当前路径填哪些选项
    static int[]path=new int[13];
    static int []a=new int[5];
    //cur是当前值
    public static boolean isSame(int pos,int cur){
        for(int i=0;i<pos;i++){
            //假如和前面的不对,就是false
            if(same[i][pos]==true&&path[i]!=cur) return false;
        }
        return true;
    }
    
    public static void dfs(int pos){
        if(pos>12) {
            ret++; 
            return;
        }
        for(int i=1;i<=4;i++){
            //看看有没有剩余次数
            if(a[i]==0)continue;
            //假如当前位置应该喝某某位置一样,但是却不相同,
            if(!isSame(pos,i))continue;
            //这个位置不用回溯,因为会用其他的给覆盖住
            path[pos]=i;
            a[i]--;
            dfs(pos+1);
            a[i]++;
        }
      
    }
  public static void main(String[]args){
      Scanner in=new Scanner(System.in);  
      for(int i=1;i<=4;i++){
          a[i]=in.nextInt();
      }
      int m=in.nextInt();
      for(int i=0;i<m;i++){
          int x=in.nextInt();
          int y=in.nextInt();
          same[x][y]=same[y][x]=true;
      }
      //从1位置开始计数
      dfs(1);
      System.out.print(ret);
  }
}

牛客.接雨水

思想,可以先求出,第一个柱子能存多少雨水,。。。只要我们能存每个柱子最多能存多少水

求出每一根柱子上能存多少雨水,把所有的柱子累加起来就可以

一根柱子上面最多存多少水?

和实际相结合,假如有这么多柱子,假如只往这一根柱子上下雨。

假如右边比你小,你下雨应该想给右边填满之后,然后在一起填

然后你假如更右边比你这个高之后,会到这个右边稍微高一点的停一下,直到把旁边那个也填满

换句话,她这个更偏向于,盛水左右的最大高度,,一个柱子能盛多少水,是看左右两边较高的给他挡着,不然就会溢出出,受左右两边较高的柱子里面,较低的那个柱子影响

lmax[i],rmax[i]左右两个高的柱子,然后最小值

把从0到最后,每一根柱子里面

min(left[i],right[i])-height[i]

预处理两个数组,left[i]和right[i],从0到i 和从i到n-1柱子   (细节就是我们要考虑当前这根柱子,因为有可能我们当前柱子就是最大值,此时左侧和右侧最大会出现负数,所以包含自己,那么减去就是0)  里面的最大值

这个解法,纯纯五星,就是非常好理解

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * max water
     * @param arr int整型一维数组 the array
     * @return long长整型
     */
    public long maxWater (int[] arr) {
       int n=arr.length;
       int[]left=new int[n];
       int[]right=new int[n];
       left[0]=arr[0];
       for(int i=1;i<n;i++){
        left[i]=Math.max(left[i-1],arr[i]);
       }
       right[n-1]=arr[n-1];
       for(int i=n-2;i>=0;i--){
        right[i]=Math.max(right[i+1],arr[i]);
       }
       long sum=0;
       for(int i=1;i<n-1;i++){
        sum+=Math.min(left[i],right[i])-arr[i];
       }
      return sum;

    }
}

牛客.加减

贪心,尽量选择一些比较挨的近的数,让他们变成相同

排序:枚举所有的区间,找出区间内所有数变成相同的数的最小代价,cost<=k

区间长度

此时你进行找的时候,会超时的,所以,枚举区间内最小代价,

如何求,一个区间的最小代价cost, (数学问题,数轴上有一些点,选取一个位置,使所有点到到他的位置最小

结论:选择最中间的点,花费的代价最小(点,不是数)

cost: a3-a3. ,a3-a2    a3-a1    a4-a3     a5-a3     

假如是a3 右边的点 偏移量为x

a3-a3+变化量x

a3+变化量x-a2

a3+变化量x-a1

a4-变化量x-a3

a5-a3-变化量x          其中 第二个和第三个都是+变化量 ,第4和5都是-变化量

上面那个图,变化量x就是a3到x的距离。 

假如偶数的点,那么你左右都可以。

优化一:前缀和求最小代价cost

cost=a3-a2      +a3-a1     +     a4-a3+       a5-a3+         a6-a3

        = 2*a3      - (a1+a2)+       (a4+a5+a6)   -   3*a3      (求一段区间内,快速求,使用前缀和)

第二个优化:

滑动窗口来优化,

1 , 3, 6 ,8 ,20

left    

right 

import java.util.*;
public class Main{
    static  int n;
    static long []sum;
    static long[]a;
    public static long cal(int l,int r){
        int mid=(l+r)/2;
     return  (mid-l)*a[mid]-(sum[mid-1]-sum[l-1])+
         (sum[r]-sum[mid])-(r-mid)*a[mid]; 
    }

    public static void main(String[]args){
        Scanner in=new Scanner(System.in);
        n=in.nextInt();
        long k=in.nextLong();
        sum=new long[n+1];
        a=new long[n+1];
        for(int i=1;i<=n;i++){
            a[i]=in.nextLong();
        }
        Arrays.sort(a);
        
        //前缀和
        for(int i=1;i<=n;i++){
            sum[i]=sum[i-1]+a[i];
        }

        int l=1;
        int r=1;
        long ret=1;
        while(r<=n){
            long cost=cal(l,r);
            while(cost>k){
                l++;
                cost=cal(l,r);
            }
            ret=Math.max(r-l+1,ret);
            r++;
        }
        System.out.print(ret);
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到