洛谷DP_递增子序列洛谷DP_输出格式_02
package Week4;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;

/*展开
题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。
某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入导弹依次飞来的高度(雷达给出的高度数据是≤50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入格式
1行,若干个整数(个数\le 100000≤100000)

输出格式
2行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入输出样例
输入 
389 207 155 300 299 170 158 65
输出 
6
2*/

//1.求最长不递增子序列的长度
//2.求最长递增子序列的长度
public class P1020 {
    static int arr[][] = new int[100002][2];
       static int arr1[][] = new int[100002][2];
       static int tree[];
       static int tree1[];
       static int num;
       static int num2;
       public static void main(String[] args) throws Exception {
            //System.setIn(new FileInputStream("src/test/Travel.txt"));
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            StringTokenizer st = new StringTokenizer(br.readLine());
            int i = 1;
            while(st.hasMoreTokens()) {
                arr[i][0] = i;
                arr[i][1] = Integer.parseInt(st.nextToken());
                arr1[i][0]=arr[i][0];
                arr1[i][1]=arr[i][1];
                i++;
            }
            //最长不递增子序列,值降序,索引升序
            Arrays.sort(arr, 1, i, new Comparator<int []>() {
                @Override
                public int compare(int[] o1, int[] o2) {
                    return o1[1]==o2[1]?o1[0]-o2[0]:o2[1]-o1[1];
                }
            });
            //最长递增子序列,值升序,索引降序
            Arrays.sort(arr1, 1, i, new Comparator<int []>() {
                @Override
                public int compare(int[] o1, int[] o2) {
                    return o1[1]==o2[1]?o2[0]-o1[0]:o1[1]-o2[1];
                }
            });
            
            int L =1;
            while(L<i) {
                L=L+L;
            }
            tree=new int[2*L];
            tree1=new int[2*L];
            num = 0;
            num2= 0;
            for (int j = 1; j <= i-1; j++) {
                int idx = arr[j][0];
                int q = queryMax1(L,L+idx-1);
                updateMax1(L+idx-1,q+1);
            }
            System.out.println(tree[1]);
            for (int j = 1; j <= i-1; j++) {
                int idx = arr1[j][0];
                int q = queryMax(L,L+idx-1);
                updateMax(L+idx-1,q+1);
            }
            System.out.println(tree1[1]);
       }
       
       public static void updateMax(int idx,int val) {
           tree1[idx]=val;
           idx=idx/2;
           while(idx>0) {
               tree1[idx]=Math.max(tree1[idx*2], tree1[idx*2+1]);
               idx=idx/2;
           }
       }
       
       public static int queryMax(int s,int e) {
           int result = 0;
           while(s<=e) {
               if(s%2==1) {
                 result=Math.max(result, tree1[s]);  
               }
               if(e%2==0) {
                   result=Math.max(result, tree1[e]); 
               }
               s=(s+1)/2;
               e=(e-1)/2;
           }
           return result;
       }
       
       public static void updateMax1(int idx,int val) {
           tree[idx]=val;
           idx=idx/2;
           while(idx>0) {
               tree[idx]=Math.max(tree[idx*2], tree[idx*2+1]);
               idx=idx/2;
           }
       }
       
       public static int queryMax1(int s,int e) {
           int result = 0;
           while(s<=e) {
               if(s%2==1) {
                 result=Math.max(result, tree[s]);  
               }
               if(e%2==0) {
                   result=Math.max(result, tree[e]); 
               }
               s=(s+1)/2;
               e=(e-1)/2;
           }
           return result;
       }
       
   
   
}
View Code
洛谷DP_递增子序列洛谷DP_输出格式_02
package Week4;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

/*输入格式
第一行有 2 个整数 T(1≤T≤1000)和 M(1≤M≤100),用一个空格隔开,T 代表总共能够用来采药的时间,M 代表山洞里的草药的数目。
接下来的 M 行每行包括两个在 1 到 100 之间(包括 1 和 100)的整数,分别表示采摘某株草药的时间和这株草药的价值。
输出格式
输出在规定的时间内可以采到的草药的最大总价值。
*/
//70 3
//71 100
//69 1
//1 2
public class P1048 {
    static int T,M;
    static int dp[];
    static int arr[][];
    public static void main(String[] args) throws Exception {
        System.setIn(new FileInputStream("Solution.txt"));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        T = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        dp = new int[T+1];
        Arrays.fill(dp, 0);
        arr = new int[M+1][2];
        for (int i = 1; i <= M; i++) {
            st = new StringTokenizer(br.readLine());
            arr[i][0]=Integer.parseInt(st.nextToken());
            arr[i][1]=Integer.parseInt(st.nextToken());
        }
        //0 1 背包
        for (int i = 1; i <= M; i++) {
            for (int j = T; j > 0; j--) {
                if(j >= arr[i][0]) {
                    dp[j]=Math.max(dp[j], dp[j-arr[i][0]]+arr[i][1]);
                }
            }
        }
        System.out.println(dp[T]);
        
    }

}
View Code
洛谷DP_递增子序列洛谷DP_输出格式_02
package Week4;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

/*
主要思路是:先开一个二维数组b[][],存储放i种j盆花的方案总数。
首先进行初始化,大家想想,无论有多少种花,如果一盆都没有,那是不是只有一种方案总数了(什么也不放)?
所以初始化为b[i][0]=1(0<=i<=m)。然后呢,我们进行三重循环。变量i表示有多少种花,j表示有多少盆花,k则是用于计算某种花放多少盆。
从总盆数开始循环到总盆数-最大盆数,如果k小于0(说明最大盆数大于总盆数)就退出循环。我们得到的状态转移方程则是:
b[i][j]+=b[i-1][k](j>=k>=j-a[i])
最终的答案就是b[n][m]。
*/
public class P1077 {
    static int N,M;
    static int A[];
    static int mod = 1000007;
    static int dp[][];

    /*
     * 根据上述对题目的分析,递推公式也很显然了,假设状态转移都保存在数组 dp[i][j] 中,第一维表示当前对第i种花作分析,
     * 第二维表示当前摆放的所有的花盆数量和。递推公式如下: dp[i][j] = dp[i-1][j] + dp[i-1][j-1] + …dp[i-1][j-ai] 
     * dp[i][j]的含义是放第 i 种花时,花盆总数刚好是 j ,第 i 种花最多有 ai 盆,
     * 所以dp[i-1]中只要花盆数量大于j-ai的情况都能凑成 dp[i][j]。
     */
    public static void main(String[] args) throws Exception{
           System.setIn(new FileInputStream("Solution.txt"));
           BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
           StringTokenizer st = null;
           st = new StringTokenizer(br.readLine());
           N = Integer.valueOf(st.nextToken());
           M = Integer.valueOf(st.nextToken());
           A = new int[N+1];
           dp = new int [N+1][M+1];
           st = new StringTokenizer(br.readLine());
           for (int i = 1; i <= N; i++) {
              A[i]=Integer.valueOf(st.nextToken());
           }
           dp[0][0]=1;
           for (int i = 1; i <= N; i++) {//变量i表示有多少种花,
             for (int j = 0; j <= M; j++) {//j表示有多少盆花,
                 for(int k=0;k<=A[i];k++) {//k则是用于计算某种花放多少盆。
                     if(j-k>=0) {
                         dp[i][j] = (dp[i][j] + dp[i-1][j-k])%mod;
                     }
                 }
                 
             }
          }
           System.out.println(dp[N][M]);
           
    }
}
View Code
洛谷DP_递增子序列洛谷DP_输出格式_02
package Week4;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

//完全背包

/*
1.每种草药可以无限制地疯狂采摘。
2.药的种类眼花缭乱,采药时间好长好长啊!师傅等得菊花都谢了!
输入格式
输入第一行有两个整数,分别代表总共能够用来采药的时间 t 和代表山洞里的草药的数目 m。
第 2 到第 (m + 1) 行,每行两个整数,第 (i+1) 行的整数 ai, bi分别表示采摘第 i 种草药的时间和该草药的价值。
输出格式
输出一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。

输入输出样例
输入 
70 3
71 100
69 1
1 2*/
public class P1616 {
   static int T,M;
   static int arr[][];
   static long dp[];
   static long ans;
   public static void main(String[] args) throws Exception {
      System.setIn(new FileInputStream("Solution.txt"));
      BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
      StringTokenizer st = new StringTokenizer(br.readLine());
      T = Integer.parseInt(st.nextToken());
      M = Integer.parseInt(st.nextToken());
      arr = new int[M+1][2];
      dp = new long[T+1];
      for (int i = 1; i <= M; i++) {
         st = new StringTokenizer(br.readLine());
         arr[i][0]=Integer.parseInt(st.nextToken());
         arr[i][1]=Integer.parseInt(st.nextToken());
      }
       //0 1 背包
//        for (int i = 1; i <= M; i++) {
//            for (int j = T; j > 0; j--) {
//                if(j >= arr[i][0]) {
//                    dp[j]=Math.max(dp[j], dp[j-arr[i][0]]+arr[i][1]);
//                }
//            }
//        }
      //完全背包
      for (int i = 1; i <= M; i++) {
        for (int j = arr[i][0]; j <= T; j++) {
            dp[j]=Math.max(dp[j], dp[j-arr[i][0]]+arr[i][1]);
        }
      }
      System.out.println(dp[T]);
   }
   
}
View Code
洛谷DP_递增子序列洛谷DP_输出格式_02
package Week4;


//多重背包

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

/*题目描述
终于,破解了千年的难题。小 FF 找到了王室的宝物室,里面堆满了无数价值连城的宝物。
这下小 FF 可发财了,嘎嘎。但是这里的宝物实在是太多了,小 FF 的采集车似乎装不下那么多宝物。看来小 FF 只能含泪舍弃其中的一部分宝物了。
小 FF 对洞穴里的宝物进行了整理,他发现每样宝物都有一件或者多件。他粗略估算了下每样宝物的价值,之后开始了宝物筛选工作:
小 FF 有一个最大载重为 W 的采集车,洞穴里总共有 n种宝物,每种宝物的价值为 vi,重量为wi,每种宝物有mi件。小 FF 希望
在采集车不超载的前提下,选择一些宝物装进采集车,使得它们的价值和最大。
输入格式
第一行为一个整数 n 和 W,分别表示宝物种数和采集车的最大载重。
接下来 n行每行三个整数 vi,wi,mi。
输出格式
输出仅一个整数,表示在采集车不超载的情况下收集的宝物的最大价值。*/
public class P1776 {
    static int N,W;
    static int v[];
    static int w[];
    static int m[];
    static int dp[];
    static int ans;
    static int weight[];//重新分堆后重量
    static int valNew[];//重新分堆后的价格
   public static void main(String[] args) throws Exception{
      System.setIn(new FileInputStream("Solution.txt"));
      BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
      StringTokenizer st = new StringTokenizer(br.readLine());
      N = Integer.parseInt(st.nextToken());
      W = Integer.parseInt(st.nextToken());
      v = new int[N+1];
      w = new int[N+1];
      m = new int[N+1];
      dp = new int[W+1];
      weight = new int[100005];
      valNew = new int[100005];
      int cnt=1;
      for (int i = 1; i <= N; i++) {
          st = new StringTokenizer(br.readLine());
          int vi = Integer.parseInt(st.nextToken());
          int wi = Integer.parseInt(st.nextToken());
          int mi = Integer.parseInt(st.nextToken());
          v[i]=vi;
          w[i]=wi;
          m[i]=mi;
      }
      for (int i = 1; i <= N; i++) {
          int vi = v[i];
          int wi = w[i];
          int mi = m[i];
          //二进制分堆
          for (int j = 1; j <= mi; j=j*2) {
            weight[cnt]=j*wi;
            valNew[cnt]=j*vi;
            mi = mi-j;
            cnt++;
          }
          //任何一个数都可以通过二进制的数相加得到,最后一个剩余的数单独成一堆
          if(mi > 0) {
              weight[cnt]=mi*wi;
              valNew[cnt]=mi*vi;
              cnt++;
          }
      }
      
      //重新分堆后等价于0/1背包
      for (int i = 1; i <= cnt; i++) {
         for (int j = W; j >= weight[i]; j--) {
            dp[j]=Math.max(dp[j], dp[j-weight[i]]+valNew[i]);
        }
      }
      
      
      System.out.println(dp[W]);
      
      
  }
   
   
}
View Code
洛谷DP_递增子序列洛谷DP_输出格式_02
package Week4;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
//求X和Y的最长公共子序列长度。
public class P2543 {
   static int arr[];
   static int arr1[];
   static int dp[][];
   static int ans;
   //01010101010 00000011111
   public static void main(String[] args) throws Exception {
      System.setIn(new FileInputStream("Solution.txt"));
      BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
      String str = br.readLine();
      String strs[] = str.split(" ");
      int N = strs[0].length();
      int M = strs[1].length();
      arr = new int[N+1];
      arr1=new int[M+1];
      dp = new int[N+1][M+1];
      for (int i = 1; i <= N; i++) {
          int x = Integer.parseInt(strs[0].substring(i-1, i));
          arr[i]=x;
      }
      for (int i = 1; i <= M; i++) {
          int x = Integer.parseInt(strs[1].substring(i-1, i));
          arr1[i]=x;
      }
      //求最长公共字串的代码
      for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            if(arr[i]==arr1[j]) {
                dp[i][j]=dp[i-1][j-1]+1;
            }else {
                dp[i][j]=Math.max(dp[i-1][j], dp[i][j-1]);
            }
        }
      }
      System.out.println(dp[N][M]);
      
   }
}
View Code