zoukankan      html  css  js  c++  java
  • UVALive 4212

    Little Charlie is a nice boy addicted to candies. He is even a subscriber to All Candies Magazine and was selected to participate in the International Candy Picking Contest.

    In this contest a random number of boxes containing candies are disposed in M rows with N columns each (so, there are a total of M × N boxes). Each box has a number indicating how many candies it contains.

    The contestant can pick a box (any one) and get all the candies it contains. But there is a catch (there is always a catch): when choosing a box, all the boxes from the rows immediately above and immediately below are emptied, as well as the box to the left and the box to the right of the chosen box. The contestant continues to pick a box until there are no candies left.

    The figure bellow illustrates this, step by step. Each cell represents one box and the number of candies it contains. At each step, the chosen box is circled and the shaded cells represent the boxes that will be emptied. After eight steps the game is over and Charlie picked 10+9+8+3+7+6+10+1 = 54 candies.

    For small values of M and N, Charlie can easily find the maximum number of candies he can pick, but when the numbers are really large he gets completely lost. Can you help Charlie maximize the number of candies he can pick?

    Input

    The input contains several test cases. The first line of a test case contains two positive integers M and N (1 ≤ M×N ≤ 105 ), separated by a single space, indicating the number of rows and columns respectively. Each of the following M lines contains N integers separated by single spaces, each representing the initial number of candies in the corresponding box. Each box will have initially at least 1 and at most 103 candies. The end of input is indicated by a line containing two zeroes separated by a single space

    Output

    For each test case in the input, your program must print a single line, containing a single value, the integer indicating the maximum number of candies that Charlie can pick

    Sample Input

    5 5

    1 8 2 1 9

    1 7 3 5 2

    1 2 10 3 10

    8 4 7 9 1

    7 1 3 1 6

    Sample Output

    54

    水dp

    一开始觉得n m的范围很大,仔细一看才知道n*m<=100000。。。。

    我们可以每一行进行一次dp得到这一行的最大值  构造数组 a  然后对a数组在进行一次dp.

    横着dp和竖着dp的状态转移是一样的   dp[i]=max(dp[i-1],dp[i-2]+a[i])   即前i个数能得到的最大值

    /* ***********************************************
    Author        :guanjun
    Created Time  :2016/10/7 12:08:19
    File Name     :la4212.cpp
    ************************************************ */
    #include <bits/stdc++.h>
    #define ull unsigned long long
    #define ll long long
    #define mod 90001
    #define INF 0x3f3f3f3f
    #define maxn 10010
    #define cle(a) memset(a,0,sizeof(a))
    const ull inf = 1LL << 61;
    const double eps=1e-5;
    using namespace std;
    priority_queue<int,vector<int>,greater<int> >pq;
    struct Node{
        int x,y;
    };
    struct cmp{
        bool operator()(Node a,Node b){
            if(a.x==b.x) return a.y> b.y;
            return a.x>b.x;
        }
    };
    
    bool cmp(int a,int b){
        return a>b;
    }
    vector<int>v[100010];
    int dp[100010];
    int a[100010];
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        #endif
        //freopen("out.txt","w",stdout);
        int n,m,x;
        while(cin>>n>>m){
            if(n==0&&m==0)break;
            for(int i=1;i<=n;i++){
                v[i].clear();
                for(int j=1;j<=m;j++){
                    scanf("%d",&x);
                    v[i].push_back(x);
                }
            }
            //先横着dp  再竖着dp
            cle(a);
            for(int i=1;i<=n;i++){
                m=v[i].size();
                cle(dp);
                for(int j=0;j<m;j++){
                    if(j<2)dp[j]=max(dp[j-1],v[i][j]);
                    else dp[j]=max(dp[j-2]+v[i][j],dp[j-1]);
                }
                //cout<<"hang "<<dp[m-1]<<endl;
                a[i]=dp[m-1];
            }
            //for(int i=1;i<=n;i++)cout<<a[i]<<endl;
            cle(dp);
            for(int i=1;i<=n;i++){
                if(i<=2)dp[i]=max(dp[i-1],a[i]);
                else dp[i]=max(dp[i-2]+a[i],dp[i-1]);
            }
            if(n==2)cout<<max(dp[1],dp[2])<<endl;
            else cout<<dp[n]<<endl;
        }
        return 0;
    }

    更新:2018.6.15

    /* ***********************************************
    Author        :guanjunace@foxmail.com
    Created Time  :2018年06月15日 星期五 09时59分17秒
    File Name     :131.cpp
    ************************************************ */
    #include <iostream>
    #include <vector>
    using namespace std;
    
    int solve(vector<int>& a) {
        int len = a.size();
        vector<int> dp(len, 0);
        dp[0] = a[0];
        for (int i = 1; i < len; ++i) {
            if (i >= 2) dp[i] = max(dp[i-2] + a[i], dp[i-1]); 
            else dp[i] = max(a[i-1], a[i]);
            //cout << dp[i] << "-" << endl;
        }
        return dp[len - 1];
    }
    
    int main() {
        int n, m, x;
        while (cin >> n >> m && n && m) {
            vector<int> v;
            for (int i = 0; i < n; ++i) {
                vector<int> a;
                for (int j = 0; j < m; ++j) {
                    cin >> x;
                    a.push_back(x);
                }
                //cout << solve(a) << endl;
                v.push_back(solve(a));
            }
            cout << solve(v) << endl;
        }
        return 0;
    }
  • 相关阅读:
    python学习笔记(十一)处理json
    python学习笔记(十)常用模块
    python学习笔记(九)内置函数
    python学习笔记(八)函数return多个值,列表推导式和交换两个变量的值
    BZOJ 3675 [Apio2014]序列分割 (斜率优化DP)
    BZOJ 3126 [USACO2013 Open]Photo (单调队列优化DP)
    POJ 1821 Fence (单调队列优化DP)
    BZOJ 3326 [SCOI2013]数数 (数位DP)
    HDU 6148 Valley Numer (数位DP)
    BZOJ 2741 L (可持久化01Trie+分块)
  • 原文地址:https://www.cnblogs.com/pk28/p/5935852.html
Copyright © 2011-2022 走看看