zoukankan      html  css  js  c++  java
  • POJ #1836 型如" E[j] = opt{D+w(i,j)} "的简单DP 线性DP

    Description


    In the army, a platoon is composed by n soldiers. During the morning inspection, the soldiers are aligned in a straight line in front of the captain. The captain is not satisfied with the way his soldiers are aligned; it is true that the soldiers are aligned in order by their code number: 1 , 2 , 3 , . . . , n , but they are not aligned by their height. The captain asks some soldiers to get out of the line, as the soldiers that remain in the line, without changing their places, but getting closer, to form a new line, where each soldier can see by looking lengthwise the line at least one of the line's extremity (left or right). A soldier see an extremity if there isn't any soldiers with a higher or equal height than his height between him and that extremity. 

    Write a program that, knowing the height of each soldier, determines the minimum number of soldiers which have to get out of line. 

    Input

    On the first line of the input is written the number of the soldiers n. On the second line is written a series of n floating numbers with at most 5 digits precision and separated by a space character. The k-th number from this line represents the height of the soldier who has the code k (1 <= k <= n). 

    There are some restrictions: 
    • 2 <= n <= 1000 
    • the height are floating numbers from the interval [0.5, 2.5] 

    Output

    The only line of output will contain the number of the soldiers who have to get out of the line.

    Sample Input

    8
    1.86 1.86 1.30621 2 1.4 1 1.97 2.2
    

    Sample Output

    4

      在 POJ DISCUSS 中找到的一组很有用的测试样例:

        

    思路


      建议在做这道题之前先了解 LIS (最长上升子序列) 的 DP 解法,我之前没有接触过,所以在思考LIS问题的子状态时出现了偏差,但也很有意思,具体是什么偏差可以看这里:链接 

      设LIS问题的状态是前 i 个数字的LIS的长度且该LIS以第 i 个数字结尾,那么状态转移方程如下:

    dp[i] = max{dp[j]} +1 , ∃j < i 且 A[j] < A[i]
    or dp[i] = 1 , ∀j < i 都有 A[j] >= A[i]

      POJ 2533 是一道 LIS 的裸题,可以拿来练练。

      

      回到原题,题目的意思是让士兵排队,要排成中间高两边低的情况,使得除最中间的士兵外任何一个士兵向左或者向右看时视野不被遮挡,也就是说最中间的士兵的身高可以相等。最后输出不符合要求需要出队重新调整位置的人数。

      和我高中合唱团的排列一样,图例如下:

      

               图片来源:http://cavenkaka.iteye.com/blog/1542421

      我是这么想的,问题转化成求 LIS ,那么 LIS 中不符合递增要求的元素个数可以被表示为 “n - LIS” ,其中 n 是元素总个数。那么这道题就很简单了,先从左至右求 LIS ,后从右至左求 LIS ,最后找到两个 LIS 的最大和并满足两个 LIS 中的元素不能重复,并让 n 减去该最大和即可。

    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<cstring>
    using namespace std;
    #define INT_MIN -1
    const int MAX_N = 1000;
    int dp[MAX_N + 1];
    int dp2[MAX_N + 1];
    int main (void) {
        int n;
        cin >> n;
        vector<float> nums;
        nums.resize(n+1);
        for (int i = 1; i <= n; i++) {
            cin >> nums[i];
        }
        
        memset(dp, 0, sizeof(dp));
        dp[1] = 1;
        //从左到右求LIS
        //dp[i] 代表前i个数的最长递增子序列的长度
        for (int i = 2; i <= n; i++) {
            dp[i] = 1;
            for (int j = 1; j < i; j++) {
                if (nums[j] < nums[i] && dp[i] <= dp[j] + 1 ) { 
                        dp[i] = dp[j] + 1;
                }
            }
        }
        //从右到左求LIS
        //dp[i] 代表后 n-i+1 个数的最长递增子序列的长度
        memset(dp2, 0, sizeof(dp2));
        dp2[8] = 1; 
        for (int i = n; i >= 1; i--) {
            dp2[i] = 1;
            for (int j = n; j > i; j--) {
                if (nums[j] < nums[i] && dp2[i] <= dp2[j] + 1 ) {
                    dp2[i] = dp2[j] + 1;
                }
            }
        }
        
        //求满足先递增再递减关系的串的最大长度
        //注意递增序列中的元素与递减序列中的元素不能重复
        int ans = INT_MIN;
        for (int i = 1; i < n; i++){
            for (int j = i+1; j <= n; j++) {
                ans = std::max(ans, dp[i] + dp2[j] );
            }
        }
        //cout << "满足先递增再递减的串的最大长度是:" << ans << endl;
        
        /*
        cout << "检查 dp2 中!" << endl;
        for (int i = 0; i <= n; i++) {
            cout << dp2[i] << " ";
        }
        cout << endl;
        cout << "检查完毕!!!" << endl;
        */
        cout << n-ans << endl;
        return 0;
    }
    View Code

      

    ————全心全意投入,拒绝画地为牢
  • 相关阅读:
    数字图像处理领域就业前景
    opencv 学习方法
    学习opencv tutorials
    win64+VS2010+OPENCV2.4.9配置问题
    libsvm使用步骤
    生成libSVM的数据格式及使用方法
    一堆应该记住的概念
    static静态变量的理解
    C程第一节课
    扫雷但是不会恭喜
  • 原文地址:https://www.cnblogs.com/Bw98blogs/p/8425733.html
Copyright © 2011-2022 走看看