贴道DP的。
- /*
- Title: Alignment
- Author: Jeff
- Time: 2008/11/3
- Complexity: O(N^2);
- Result: 328K 32MS/ AC
- Reference:
- Discuss
- Description:
- 给定n个人高度,将n个人中的其中一些人出队,使得任何一个人
- 都能够看到左无穷远或右无穷远。(高度要大于才能望过去) 。求
- 出队的最少人数。
- Tips:
- 虽然是从中间出对,但是可以看成是:
- 最长递增子序列up[] + 逆序的最长递增子序列[down]
- 用n^2求出两个子序列后,我犯了一个错误,就是直接用
- n - max{up[i]+ down[i] -1| 0<=i<n)求出来。
- 但是看看以下的反例
- 3 4 5 1 2 5 4 3
- 用上面求出来是 3!WA!
- 所以用n^2改正:
- n - max{up[i]+down[j]} | 0 <= i < j < n}
- 求出结果2.
- 看来此题通过率不高也是有道理的。
- p.s.
- */
- #include <cstdio>
- #include <cstring>
- using namespace std;
- const int MAX = 1000;
- double h[MAX];
- int up[MAX];
- int down[MAX];
- int main(){
- freopen("in.txt", "r", stdin);
- freopen("out.txt", "w", stdout);
- int n;
- while(scanf("%d", &n) != EOF){
- for(int i = 0; i < n; i++)scanf("%lf", &h[i]);
- up[0] = 1;
- for(int i = 1; i < n; i++){
- up[i] = 1;
- for(int j = i - 1; j >= 0; j--){
- if(h[i] > h[j] && up[j] + 1 > up[i])
- up[i] = up[j] + 1;
- }
- }
- down[n-1] = 1;
- for(int i = n - 2; i >= 0; i--){
- down[i] = 1;
- for(int j = i + 1; j < n; j++){
- if(h[i] > h[j] && down[j] + 1 > down[i])
- down[i] = down[j] + 1;
- }
- }
- //for(int i = 0; i < n; i++)printf("%d ", up[i]);printf("/n");
- //for(int i = 0; i < n; i++)printf("%d ", down[i]);printf("/n");
- int ans = 0;
- for(int i = 0; i < n; i++)
- for(int j = i + 1; j < n; j++)
- if(ans < up[i] + down[j])
- ans = up[i] + down[j];
- printf("%d/n", n - ans);
- }
- return 0;
- }