• 11G:上机


    总时间限制: 
    1000ms
     
    内存限制: 
    65536kB
    描述

    又到周末了,同学们陆陆续续开开心心的来到机房上机。jbr也不例外,但是他到的有点晚,发现有些机位上已经有同学正在做题,有些机位还空着。细心的jbr发现,一位同学来到机房,坐在机位i上,如果他的左右两边都空着,他将获得能力值a[i];如果当他坐下时,左边或者右边已经有一个人在上机了,他将获得能力值b[i];如果当他坐下时,他的左边右边都有人在上机,他将获得能力值c[i]。

    同时他发现,已经在上机的同学不会受到刚要坐下的同学的影响,即他们的能力值只会在坐下时产生,以后不会发生变化;第一个机位左边没有机位,最后一个机位右边没有机位,无论何时坐在这两个机位上将无法获得c值。

    这时jbr发现有一排机器还空着,一共有N个机位,编号1到N。这时有N位同学们陆陆续续来到机房,一个一个按照顺序坐在这排机位上。聪明的jbr想知道怎么安排座位的顺序,可以使这N位同学获得能力值的和最大呢?

    输入
    第一行一个整数N(1<= N <= 10000)

    第二行N个数,表示a[i]

    第三行N个数,表示b[i]

    第四行N个数,表示c[i]

    (1<= a[i],b[i],c[i] <=10000)
    输出
    一个整数,表示获得最大的能力值和
    样例输入
    4
    1 2 2 4
    4 3 3 1
    2 1 1 2
    
    样例输出
    14
    提示
    第一位同学坐在第四个机位上,获得能力值4;
    第二位同学坐在第三个机位上,获得能力值3;
    第三位同学坐在第二个机位上,获得能力值3;
    第四位同学坐在第一个机位上,获得能力值4;
    总和为14。
     1 #include <iostream>
     2 #include <vector>
     3 #include <cmath>
     4 #include <algorithm>
     5 using namespace std;
     6 int a[10005];
     7 int b[10005];
     8 int c[10005];
     9 int d[10005][4]; //考虑前i的座位已经坐好的前i个座位最大值,0-第i个人坐下的时候两边没人,1-左边有人,2-右边有人,3-都有人 
    10 int main(){
    11     int n;
    12     cin >> n;
    13     int i;
    14     for(i = 1; i <= n; i++)
    15         cin>>a[i];
    16     for(i = 1; i <= n; i++)
    17         cin>>b[i];
    18     for(i = 1; i <= n; i++)
    19         cin>>c[i];
    20     d[1][0] = a[1];
    21     d[1][2] = b[1];
    22     for(i = 2; i <= n; i++){
    23         d[i][0] = max(d[i-1][3], d[i-1][2])+a[i];  //第i个位置坐下的时候两边没人,要求它先于第i-1个人被坐,也就是说第i-1个人坐下的时候一定是右边有人 
    24         d[i][1] = max(d[i-1][0],d[i-1][1]) + b[i];
    25         d[i][2] = max(d[i-1][3], d[i-1][2])+b[i];
    26         d[i][3] = max(d[i-1][0], d[i-1][1])+c[i];
    27     }
    28     cout<<max(d[n][0],d[n][1]);
    29     return 0;
    30 }

    备注:像这种在一个一维数组上动规,首先要考虑的状态肯定还是“考虑前i个和前i-1个的关系”。但是我想了一会儿觉得无从下手,因为第i个座位被坐下时候的得分不光跟前i-1个座位有关啊!还跟第i+1个座位是否有人有关,然后我就放弃了,觉得没法做。

    但其实所谓有关,我们完全可以保留这种对于i+1的“不确定性”,或者说在算i时,先记录对应的i+1的每种可能(已经有人坐或者没人坐)下的i(这是因为我们在算i的时候并不需要用到i+1的结果,只是用到了i+1的状态(有人坐或者没人坐)),在推i+1的时候再反过来用到i。通过加一维数组实现,我觉得这是这道题所带来最大的启发。

    【考虑前i个座位已经坐好了的前i个座位最大值】就是体现了这个道理。也就是说,不管第i+1个座位是否有人坐(这个状态已经考虑在了d[i][?]里),我们只关心前i个座位得到的最大值,不需要考虑第i+1的得分。

    还有就是,这道题是按照空间顺序递推,而不是时间上,时间上的变化已经体现在了第二维状态里面。

    我因为转移方程没考虑清楚的错误已经WA了好几次。一定要想清楚,在第i个人坐下的时候的每种状态,对应的第i-1的状态应该是什么。

  • 相关阅读:
    攀岩
    插入排序
    runtime error
    vector
    旅行家
    九键字母组合
    [蓝桥杯][基础训练]Sine之舞
    代码计算程序运行的时间
    max_element
    distance
  • 原文地址:https://www.cnblogs.com/fangziyuan/p/13149463.html
Copyright © 2020-2023  润新知