码迷,mamicode.com
首页 > 其他好文 > 详细

POJ #1836 型如" E[j] = opt{D+w(i,j)} "的简单DP 线性DP

时间:2018-02-07 14:41:29      阅读:146      评论:0      收藏:0      [点我收藏+]

标签:open   hid   one   target   http   排列   cto   简单   tar   

Description


 

  题目详情和测试样例在这里:链接

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

    技术分享图片

 

思路


 

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

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

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

  技术分享图片

           图片来源: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

 

 

  

POJ #1836 型如" E[j] = opt{D+w(i,j)} "的简单DP 线性DP

标签:open   hid   one   target   http   排列   cto   简单   tar   

原文地址:https://www.cnblogs.com/Bw98blogs/p/8425733.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!