ShineYoung

导航

 

HDU-1284

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=1284

这是一道背包类型的动态规划题目,题目意思是N块钱,可以有1,2,3元组成,问你有几种兑换方法,简单思考一下,假如说有n元钱,求f(n),f(n)= f(n-1)+f(n-2)+f(n-3)

然后接下来递推或者递归都ok

import java.util.*;
public class Main {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int dp[][] = new int[4][32768];
        for (int i = 1; i < 4; i++) {
            dp[i][0] = 1;
        }
        for (int j = 1; j < 32768; j++) {
            dp[1][j] = 1;
        }
        for (int i = 1; i < 4; i++) {
            for (int j = 1; j < 32768; j++) {
                if (i > j) {
                    dp[i][j] = dp[i - 1][j];
                } else
                    dp[i][j] = dp[i - 1][j] + dp[i][j - i];
            }
        }
        while (in.hasNext()) {
            int n = in.nextInt();
            System.out.println(dp[3][n]);
        }
    }
}

 

 

求最长递增子序列,同样是动态规划的一种类型,代码复制自https://www.jianshu.com/p/ae71823744b3

public class Main {
    
    public static int lis(int [] array)
    {
        int []lis = new int[array.length];
        int[] pre=new int[array.length];
        for(int i =0;i<array.length;i++)
        {
            lis[i]=1;
            pre[i]=i;
        }
         for (int j=1; j<array.length; j++) {  
                for (int i=0; i<j; i++) {  
                    if (array[j]>array[i] && lis[j]<lis[i]+1){ //注意array[j]<array[i]+1这个条件,不能省略。  
                        lis[j] = lis[i] + 1; //计算以array[j]结尾的序列的最长递增子序列长度  
                        pre[j]=i;
                    }  
                }  
            }  
        
        int max=0,index = 0;
        for(int k=0;k<lis.length;k++)
        {
            if(lis[k]>max){
                max=lis[k];
                index=k;
            }
        }
        System.out.println("最长递增子序列长度:"+max);
        Stack<Integer> stack=new Stack<Integer>();  
        while(index!=pre[index]){
            //System.out.print(array[index]+" ");   
            stack.push(array[index]);
            index=pre[index];       
        }

        if(index==pre[index])
        //  System.out.print(array[index]+" ");
            stack.push(array[index]);
        while(!stack.isEmpty())
            System.out.print(stack.pop()+" ");          
        return max;
    }
    
    
    public static void main(String[] args){
        int[] array={35, 36, 39, 3, 15, 27, 6, 42};
        lis(array);
    }
    
}

 

 

华为机试题合唱队(题目来自牛课网) 

题目描述

计算最少出列多少位同学,使得剩下的同学排成合唱队形

说明:

N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。 
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,   则他们的身高满足存在i(1<=i<=K)使得T1<T2<......<Ti-1<Ti>Ti+1>......>TK。 
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。 

 

 

输入描述:

整数N

输出描述:

最少需要几位同学出列

示例1

输入

8
186 186 150 200 160 130 197 200

输出

4
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            int num = in.nextInt();
            in.nextLine();
            int[] lis = new int[num];

            for (int i = 0; i < num; i++) {
                lis[i] = in.nextInt();
            }

            int[] first = new int[num];
            int[] last = new int[num];

            for (int i = 0; i < last.length; i++) {
                first[i] = 1;
                last[i] = 1;
            }

            for (int i = 0; i < first.length; i++) {
                for (int j = 0; j < i; j++) {
                    if (lis[i] > lis[j] && first[i] < first[j] + 1) {
                        first[i] = first[j] + 1;
                    }
                }
            }

            for (int i = last.length - 1; i >= 0; i--) {
                for (int j = last.length - 1; j > i; j--) {
                    if (lis[i] > lis[j] && last[i] < last[j] + 1) {
                        last[i] = last[j] + 1;
                    }
                }
            }

            int max = 0;
            for (int i = last.length - 1; i >= 0; i--) {
                //System.out.println(last[i]);
                if (max < first[i] + last[i]) {
                    max = first[i] + last[i];
                }
            }
            System.out.println(num - max + 1);
        }
    }
}

分析一下,这道题目要我们求的是一个最大递增子串加上最大递减字串

所以我们可以正向求最大递增子串,再反向求最大递增字串,然后每个数字对应的最大递增字串长度和反向最大递增字串长度加起来值最大的就是我们要求的值,然后这个数字重复计入了字串长度

所以总数-这个数字+1就是我们要的最少出列人数

posted on 2019-03-10 12:51  ShineYoung  阅读(119)  评论(0编辑  收藏  举报