• LightOJ1283 Shelving Books(DP)


    题目

    Source

    http://www.lightoj.com/volume_showproblem.php?problem=1283

    Description

    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, 105]. The ith integer denotes the height of the ith book from left.

    Output

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

    Sample Input

    2
    5
    3 9 1 5 8
    8
    121 710 312 611 599 400 689 611

    Sample Output

    Case 1: 4
    Case 2: 6

    分析

    题目大概说有n本书,要依次把它们放到书架,可以放到书架的左边或者右边挨着已经放好的书的下一个位置,当然也可以选择不放。放好后要保证书的高度从左到右非递减。问最多能放上几本书。

    n才100,果断这么表示状态:

    • dp[i][j][k]表示放置前i本书,书架的左边最后面的书是第j本且书架右边最前面的书是第k本,最多能放的书数

    转移我用我为人人,通过dp[i-1]的状态选择将第i本书放到左边还是右边或者不放来转移并更新dp[i]的状态值。

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int d[111][111][111];
    int main(){
        int t,n,a[111];
        scanf("%d",&t);
        for(int cse=1; cse<=t; ++cse){
            scanf("%d",&n);
            for(int i=1; i<=n; ++i){
                scanf("%d",&a[i]);
            }
            memset(d,-1,sizeof(d));
            d[0][0][0]=0;
            for(int i=0; i<n; ++i){
                for(int j=0; j<=i; ++j){
                    for(int k=0; k<=i; ++k){
                        if(d[i][j][k]==-1) continue;
                        d[i+1][j][k]=max(d[i+1][j][k],d[i][j][k]);
                        if(j==0 && k==0){
                            d[i+1][i+1][0]=1;
                            d[i+1][0][i+1]=1;
                        }else if(j==0){
                            if(a[k]>=a[i+1]) d[i+1][i+1][k]=max(d[i+1][i+1][k],d[i][j][k]+1);
                            if(a[k]>=a[i+1]) d[i+1][j][i+1]=max(d[i+1][j][i+1],d[i][j][k]+1);
                        }else if(k==0){
                            if(a[i+1]>=a[j]) d[i+1][i+1][k]=max(d[i+1][i+1][k],d[i][j][k]+1);
                            if(a[i+1]>=a[j]) d[i+1][j][i+1]=max(d[i+1][j][i+1],d[i][j][k]+1);
                        }else{
                            if(a[j]<=a[i+1] && a[i+1]<=a[k]){
                                d[i+1][i+1][k]=max(d[i+1][i+1][k],d[i][j][k]+1);
                                d[i+1][j][i+1]=max(d[i+1][j][i+1],d[i][j][k]+1);
                            }
                        }
                    }
                }
            }
            int res=0;
            for(int i=0; i<=n; ++i){
                for(int j=0; j<=n; ++j){
                    res=max(res,d[n][i][j]);
                }
            }
            printf("Case %d: %d
    ",cse,res);
        }
        return 0;
    }
    
  • 相关阅读:
    “约瑟夫问题”实现代码
    “百钱买百鸡”问题
    链栈的表示与实现
    个人作品Demo3PLY文件的读取
    系统程序员成长计划容器与算法(一)(下)
    循环单链表的建立
    链式队列元素删除实现
    使用链栈实现数制的转换
    系统程序员成长计划容器与算法(二)(上)
    个人作品Demo4STL文件读取
  • 原文地址:https://www.cnblogs.com/WABoss/p/5765310.html
Copyright © 2020-2023  润新知