zoukankan      html  css  js  c++  java
  • b_51_最大M字段和(两个状态表示+两种决策)

    将给定的N个数划分为互不相交的M个子段,并且这M个子段的和是最大的

    思路
    f[i][j]表示将前i个数划分成j段后的最大和,下面是决策:

    • f[i-1][j]:将a[j]接在第j段后面
    • f[k][j-1]:a[j]另起一段,但因为加上只有a[j]这单独的一段后已经一共有j段了,所以需要从前f[k][j-1]中选j-1段最大的(k∈[i-1,j)),但前i-1段必须每段都要有一个数字把,所以k最小取i-1

    注:并不需要用完n个数哦,但还是超时了啊

    import java.util.*;
    import java.math.*;
    import java.io.*;
    class Solution {
        int n,m;
        long a[],f[][];
        void init() throws IOException {
            Scanner sc = new Scanner(new BufferedInputStream(System.in));
            n=sc.nextInt(); m=sc.nextInt(); a=new long[n+5]; f=new long[n+5][m+5];
            for (int i=1; i<=n; i++) a[i]=sc.nextLong();
            if (m>=n) {
                long s=0; for (int i=1; i<=n; i++) s+=a[i];
                System.out.println(s);
            } else {
                long mx=0;
                for (int j=1; j<=m; j++)
                for (int i=1; i<=n; i++) {
                    f[i][j]=Math.max(f[i][j], f[i-1][j]+a[i]);
                    for (int k=j-1; k<i; k++) //第i个数自己起一段,从(j-1,i-1)个数中选j-1段
                        f[i][j]=Math.max(f[i][j], f[k][j-1]); 
                    mx=Math.max(mx, f[i][j]);
                }
                System.out.println(mx);
            }
        }
    }
    public class Main{
        public static void main(String[] args) throws IOException {  
            Solution s = new Solution();
            s.init();
        }
    }
    

    最里面那层循环其实省去的,为什么?因为每次它的起始位置是j-1,终点是随着i的增加而增加,所以可作出等价变换

    import java.util.*;
    import java.math.*;
    import java.io.*;
    class Solution {
        int n,m;
        long a[],f[][];
        void init() throws IOException {
            Scanner sc = new Scanner(new BufferedInputStream(System.in));
            n=sc.nextInt(); m=sc.nextInt(); a=new long[n+5]; f=new long[n+5][m+5];
            for (int i=1; i<=n; i++) a[i]=sc.nextLong();
            if (m>=n) {
                long s=0; for (int i=1; i<=n; i++) s+=a[i];
                System.out.println(s);
            } else {
                long mx=0;
                for (int j=1; j<=m; j++) {
                    long t=0;
                    for (int i=1; i<=n; i++) {
                        f[i][j]=Math.max(f[i][j], f[i-1][j]+a[i]);
                        if (i>=j) {
                            t=Math.max(t, f[i-1][j-1]); //这里不就是f[k][j-1]吗,只不过k每次都<i且≥j-1
                            f[i][j]=Math.max(f[i][j], t+a[i]);
                        }
                        mx=Math.max(mx, f[i][j]);
                    }
                }
                System.out.println(mx);
            }
        }
    }
    public class Main{
        public static void main(String[] args) throws IOException {  
            Solution s = new Solution();
            s.init();
        }
    }
    
    
  • 相关阅读:
    loadrunner -27778 https连接问题
    https调试
    Session Alerts
    Pause Web Sessions
    Customize Web Sessions List
    单例模式:Java单例模式的几种写法及它们的优缺点
    Activity: launchMode 和 Intent.FLAG_ACTIVITY_CLEAR_TOP
    TextView: android:ellipsize="marquee" 跑马灯效果无效的问题
    Socket通信(1):搭建开发环境
    linux: QT安装时出现段错误segmentation fault
  • 原文地址:https://www.cnblogs.com/wdt1/p/13891354.html
Copyright © 2011-2022 走看看