zoukankan      html  css  js  c++  java
  • P3089 [USACO13NOV]POGO的牛Pogo-Cow

    FJ给奶牛贝西的脚安装上了弹簧,使它可以在农场里快速地跳跃,但是它还没有学会如何降低速度。

    FJ觉得让贝西在一条直线的一维线路上进行练习,他在不同的目标点放置了N (1 <= N <= 1000)个目标点,目标点i在目标点x(i),该点得分为p(i)。贝西开始时可以选择站在一个目标点上,只允许朝一个方向跳跃,从一目标点跳到另外一个目标点,每次跳跃的距离至少和上一次跳跃的距离相等,并且必须跳到一个目标点。

    每跳到一个目标点,贝西可以拿到该点的得分,请计算他的最大可能得分。

    输入输出格式

    输入格式:

    * Line 1: The integer N.

    * Lines 2..1+N: Line i+1 contains x(i) and p(i), each an integer in the range 0..1,000,000.

    输出格式:

    * Line 1: The maximum number of points Bessie can receive.

    输入输出样例

    输入样例#1: 复制
    6 
    5 6 
    1 1 
    10 5 
    7 6 
    4 8 
    8 10 
    
    输出样例#1: 复制
    25 
    

    说明

    There are 6 targets. The first is at position x=5 and is worth 6 points, and so on.

    Bessie hops from position x=4 (8 points) to position x=5 (6 points) to position x=7 (6 points) to position x=10 (5 points).

    题意:

    给你n个点,先让你从这n个点中选择一个为起点,然后可以以这个点为起点然后选择一个方向(之后不能改变方向)开始蹦到下一个点,必须保证这一次蹦跳的距离要大于等于上一次的距离,把所有蹦跳经过的点的值加在一起就可以了

    题解:

    错误解析:

    我先跑的以x增大为正方向

    我原本想的是用一维数组dp[i],来存前i个点的蹦跳且最后一个到达的点是第i个点所获得的最大值,但是题上说了要保证这一次蹦跳的距离要大于等于上一次的距离,所以我就用了一个数组来保存这个dp[i]是从那个点蹦过来的,但是我还没有考虑周全,看一个例子:

    给出的全是点的值,他们之间距离都是相差1

    原始值       //1 7 5 10 15
    dp              //1 8 6 16
                      //         18

    可见到dp跑到10这个位置的时候会出现两个值,一个16,蹦跳距离1;另一个18,蹦跳距离2;按我的代码我会选择18,那个存上一次蹦跳位置的数组会存放第二个点

    这个时候dp到15的时候就会出错,因为从dp[4]没法向dp[5]转移,因为上一次蹦跳距离是2

    这个时候结果就会出错<_>

    正解:

    dp[i][j]表示最后的那一次蹦跳是从j到i,所以我们再求dp[i][j]的最优解的时候还要枚举以j为终点的最后一蹦的另一个点是谁,三重for循环,感觉就凉凉了,所以肯定要降低复杂度

    我们可以把i,和j枚举的顺序改变一下,这样可以在dp过程中就是在二维数组中一列一列地进行。这样有什么好处呢?

    一列一列地进行就会有i的值一直在变大,但是j不变,意思就是蹦跳距离在越来越大(蹦跳远点不变,蹦跳终点越来越远)

    这样的话我们枚举谁蹦到j是最优的时候,我们就可以倒着枚举,这样另一个点蹦跳到j的距离会越来越远,我们可以让一旦这个距离大于我们要求的

    dp[i][j]的从j——>i我们就让这个循环停止,等到下一次i变大的时候,我们再让这个k接着上一次的往更大的间距枚举

    状态转移方程:

    sum=max(dp[j][k]+m[j].p,sum);

    dp[i][j]=max(dp[i][j],sum);

    代码:

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <iostream>
     5 #include <algorithm>
     6 using namespace std;
     7 int n,ans;
     8 int f[1001][1001];
     9 struct node {
    10     int x,v;
    11     bool operator <(const node &a)const {           
    12         return x<a.x;                                 //重载运算符 
    13     }
    14 } a[1001];
    15 int main() { 
    16     scanf("%d",&n);
    17     for (int i=1; i<=n; i++)scanf("%d%d",&a[i].x,&a[i].v);
    18     sort(a+1,a+n+1);  
    19     for (int j=1; j<=n; j++) {
    20         int k=j-1,val=a[j].v;
    21         for (int i=j+1; i<=n; i++) {
    22             while ((k)and(a[i].x-a[j].x>=a[j].x-a[k].x))
    23                 val=max(val,f[j][k]+a[j].v),k--;
    24             f[i][j]=max(f[i][j],val);
    25             ans=max(ans,val+a[i].v);}
    26     //倒过来再求一次       
    27     }for (int j=n; j; j--) {
    28         int k=j+1,val=a[j].v;
    29         for (int i=j-1; i; i--) {
    30             while ((k<=n)and(a[k].x-a[j].x<=a[j].x-a[i].x))
    31                 val=max(val,f[j][k]+a[j].v),k++;
    32             f[i][j]=max(f[i][j],val);
    33             ans=max(ans,val+a[i].v);}
    34     }printf("%d
    ",ans);
    35     return 0;
    36 }
    View Code
  • 相关阅读:
    (7)常量和变量
    (6)python基础数据类型
    PEP8规范
    (5)原码反码补码
    (4)二八十六进制转换
    (3)你的第一个python程序
    (2)python开发环境搭建
    几种常见的开发语言对比
    (1)python的基础认知
    (25)线程---local数据隔离
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/11095055.html
Copyright © 2011-2022 走看看