zoukankan      html  css  js  c++  java
  • 可爱精灵宝贝:dp

    拒绝听搜索.etc水过的。数据太弱了(尽管考场上我凭借数据太水骗了好多分)

    我讲的思路和下发的题解一样。(因为我不会所以只能颓它啊)

    首先你要相信这题精灵就100个,真的只有100个,这次数据范围没错。

    然后你的复杂度就可以愉快地用m了。

    因为小精灵就m个所以实际上有用的位置也最多只有m+1个(算起点)

    可以证明:如果路径中存在折返,那么一定发生在某一个小精灵的位置上。

    因为如果你在其它位置折返,那一定不如在上一个经过的小精灵处就折返,这样才能更早到达对面的位置

    也可以证明:如果过程中走过的坐标最小是l最大是r,那么接下来要么就是直线前往l左面的第一只小精灵,要么就是直线前往r右面的第一只小精灵。

    因为l到r区间内的精灵都被你以前路过时抓走了,如果你想要更多的分数就需要扩展你的活动区间。

    而从(l,r)->(l,r+2)可以分解成(l,r)->(l,r+1)->(l,r+2)来逐步考虑,所以现在的问题就是dp统计一次往两边扩展1个位置。

    dp定义已经出来了,tl[i][j][k]表示已经走过区间j~k,目前时间为i的最大分数,此时在左端点。tr[i][j][k]同理只不过在右端点。

    然而数组开不开,需要离散化一下有小精灵的坐标。

    由本层向下一层转移就好。

    理论复杂度爆踩搜索,实际运行时间被爆踩。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 struct qs{int x,v,t;friend bool operator<(qs a,qs b){return a.x<b.x;}}q[105];
     7 int tl[2005][105][105],tr[2005][105][105],x[105],ref[2005],n,m,k,o,p,e[2005][105],ans;
     8 int main(){
     9     scanf("%d%d%d",&n,&k,&m);x[1]=k;
    10     for(int i=1;i<=m;++i)scanf("%d%d%d",&q[i].x,&q[i].v,&q[i].t),x[i+1]=q[i].x;
    11     sort(x+1,x+2+m);memset(tl,0xa0,sizeof tl);memset(tr,0xa0,sizeof tr);
    12     for(int i=1;i<=m+1;++i)if(!ref[x[i]])x[++o]=x[i],ref[x[i]]=o;
    13     for(int i=1;i<=m;++i)if(q[i].x==k)p+=q[i].v;
    14     tl[1][ref[k]][ref[k]]=tr[1][ref[k]][ref[k]]=p;
    15     for(int i=1;i<=m;++i)e[q[i].t][ref[q[i].x]]+=q[i].v;
    16     for(int i=1;i<=o;++i)for(int j=2000;j;--j)e[j][i]+=e[j+1][i];
    17     for(int t=1,T;t<=2000;++t)for(int i=1;i<=o;++i)for(int j=i;j<=o;++j){
    18         T=t+x[i]-x[i-1];if(i!=1&&T<=2000)tl[T][i-1][j]=max(tl[T][i-1][j],tl[t][i][j]+e[T][i-1]);
    19         T=t+x[j]-x[i-1];if(i!=1&&T<=2000)tl[T][i-1][j]=max(tl[T][i-1][j],tr[t][i][j]+e[T][i-1]);
    20         T=t+x[j+1]-x[j];if(j!=o&&T<=2000)tr[T][i][j+1]=max(tr[T][i][j+1],tr[t][i][j]+e[T][j+1]);
    21         T=t+x[j+1]-x[i];if(j!=o&&T<=2000)tr[T][i][j+1]=max(tr[T][i][j+1],tl[t][i][j]+e[T][j+1]);
    22         tl[t+1][i][j]=max(tl[t+1][i][j],tl[t][i][j]);
    23         tr[t+1][i][j]=max(tr[t+1][i][j],tr[t][i][j]);
    24     }
    25     for(int i=1;i<=o;++i)for(int j=i;j<=o;++j)ans=max(ans,max(tl[2000][i][j],tr[2000][i][j]));
    26     printf("%d
    ",ans);
    27 }
    码量有点大
  • 相关阅读:
    webpack 3 零基础入门教程 #3
    webpack 3 零基础入门教程 #2
    webpack 3 零基础入门教程 #1
    webpack 3 零基础入门教程 #4
    'System.Array' does not contain a definition for 'ToArray' and no extension method 'ToArray' accepting a first argument of type 'System.Array' could be found (are you missing a using directive or an a
    Excel将两列依次合并为一列
    Unity3D射线的方向
    关于非奇异矩阵
    Unity3D获取游戏屏幕大小
    JS中的路径问题
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11340234.html
Copyright © 2011-2022 走看看