poj 1836 Alignment

http://poj.org/problem?id=1836

题意:

  一队士兵排队,高低起伏。去掉最少的士兵,使得中间高两边低(单峰)。

经典LIS,注意[1~n]的最优解并不一定在dp[n]中,故需预处理。

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string>
 4 #include <string.h>
 5 #include <stdlib.h>
 6 #define EPS 1e-5
 7 #define INF 0x3f3f3f
 8 
 9 using namespace std;
10 int ans, n;
11 double num[1005];
12 int dpI[1005], dpD[1005];
13 
14 void LIS(int a, int b)
15 {    
16     for(int i=a; i<=b; i++)    
17         dpI[i] = 1;
18 
19     for(int i=a; i<=b; i++)
20     { 
21         for(int j=a; j<i; j++)
22             if(num[j]-num[i] <= -EPS)   //即num[j]<num[i]
23                 dpI[i] = max(dpI[i], dpI[j]+1);
24     }
25 }
26 
27 void LDS(int a, int b)
28 {    
29     for(int i=a; i<=b; i++)    
30         dpD[i] = 1;
31 
32     for(int i=b; i>=a; i--)
33     { 
34         for(int j=b; j>i; j--)
35             if(num[j]-num[i] <= -EPS)    //即num[j]<num[i]
36                 dpD[i] = max(dpD[i], dpD[j]+1);
37     }
38 }
39 
40 void print(int *num)
41 {
42     for(int i=0; i<n; i++)
43         cout << num[i] << " ";
44     cout << endl; 
45         
46 }
47 int main()
48 {
49     //freopen("testin.txt", "r", stdin);
50     //freopen("testUout.txt", "w", stdout);
51     
52     while(cin >> n)
53     {                
54         //dpI[i]为包含num[i]的上升子序列的最大值。         
55         for(int i=0; i<n; i++)
56             scanf("%lf", &num[i]);
57                 
58         LIS(0, n-1);
59         LDS(0, n-1);
60         
61         //预处理!!!
62         for(int i=1; i<=n-1; i++)
63             dpI[i] = max(dpI[i], dpI[i-1]);
64         for(int i=n-2; i>=n; i++)
65             dpD[i] = max(dpD[i], dpD[i+1]);
66         //print(dpI);
67         //print(dpD);
68         ans = 0x3f3f3f;
69         for(int i=0; i<n-1; i++)
70             ans = min(ans, n - dpI[i] - dpD[i+1]);
71         printf("%d\n", ans); 
72     }   
73     
74     return 0;
75 }
View Code

 

 

 

posted on 2013-06-11 16:31  KimKyeYu  阅读(165)  评论(0编辑  收藏  举报

导航