# lightoj 1283 1283 - Shelving Books(dp)

You are a librarian. You keep the books in a well organized form such that it becomes simpler for you to find a book and even they look better in the shelves.

One day you get **n** new books from one of the library sponsors. And unfortunately they are coming to visit the library, and of course they want to see their books in the shelves. So, you don't have enough time to shelve them all in the shelf in an organized manner since the heights of the books may not be same. But it's the question of your reputation, that's why you have planned to shelve them using the following idea:

1) You will take one book from the **n** books from left.

2) You have exactly one shelf to organize these books, so you may either put this book in the left side of the shelf, right side of the shelf or you may not put it in the shelf. There can already be books in the left or right side. In such case, you put the book with that book, but you don't move the book you put previously.

3) Your target is to put the books in the shelf such that from left to right they are sorted in **non-descending** order.

4) Your target is to put as many books in the shelf as you can.

You can assume that the shelf is wide enough to contain all the books. For example, you have 5 books and the heights of the books are 3 9 1 5 8 (from left). In the shelf you can put at most 4 books. You can shelve 3 5 8 9, because at first you got the book with height 3, you stored it in the left side of the shelf, then you got 9 and you put it in the right side of the shelf, then you got 1 and you ignored it, you got 5 you put it in the left with 3. Then you got 5 and you put it in left or right. You can also shelve 1 5 8 9 maintaining the restrictions.

Now given the heights of the books, your task is to find the maximum number of books you can shelve maintaining the above restrictions.

# Input

Input starts with an integer **T (≤ 200)**, denoting the number of test cases.

Each case starts with a line containing an integer **n (1 ≤ n ≤ 100)**. Next line contains **n** space separated integers from **[1, 10 ^{5}]**. The

**i**integer denotes the height of the

^{th}**i**book from left.

^{th}# Output

For each case, print the case number and the maximum number of books that can be shelved.

## Sample Input |
## Output for Sample Input |

2 5 3 9 1 5 8 8 121 710 312 611 599 400 689 611 |
Case 1: 4 Case 2: 6 |

** 题意：给你n本书，你可以从前往后挑选放在书架上，对于每一本书，你可以选择放在左边或者右边，也可以不放，问最后可以摆放的最长书本高度不单调递减的最长高度是多少。**

**思路：对于每本要放的书，我们有三种选择，放右边，放左边，不放。于是我们可以这样表示状态：dp[k][i][j]表示是对第k本书选择操作后的中间空隙左边高度为i，右边高度为j的最长长度。由于书本高度的范围，我们可以先离散化。**

#include<iostream> #include<algorithm> #include<cstdio> #include<queue> #include<map> #include<vector> #include<cstring> #include<cmath> #include<set> using namespace std; typedef long long ll; int INF = 0x3f3f3f3f; const int N = 1e2 + 10; int dp[N][N][N], a[N], b[N], c[N]; int main() { int t, n, m; cin>>t; for(int cas = 1; cas<=t; cas++) { int n; scanf("%d", &n); for(int i = 0; i<n; i++) scanf("%d", &a[i]), b[i] = a[i]; sort(a, a+n); for(int i = 0; i<n; i++) c[i+1] = lower_bound(a, a+n, b[i]) - a + 1; memset(dp, 0, sizeof(dp)); int ans = 0; for(int k = 1; k<=n; k++) { for(int i = 0; i<=n; i++) for(int j = i; j<=n+1; j++) { dp[k][i][j] = max(dp[k-1][i][j], dp[k][i][j]); if(c[k]>=i && c[k]<=j) dp[k][c[k]][j] = max(dp[k-1][i][j]+1, dp[k][c[k]][j]), dp[k][i][c[k]] = max(dp[k][i][c[k]], dp[k-1][i][j] + 1); ans = max(dp[k][i][j], max(dp[k][c[k]][j], max(ans, dp[k][i][c[k]]))); } } printf("Case %d: %d\n",cas, ans); } return 0; }

最后更新于 2016-09-01 18:17:05 并被添加「DP lightoj」标签，已有 186 位童鞋阅读过。

本站使用「署名 4.0 国际」创作共享协议，可自由转载、引用，但需署名作者且注明文章出处