LA 3983 - Robotruck 单调队列优化DP

来源:互联网 发布:无线连接网络打印机 编辑:程序博客网 时间:2024/05/18 00:33

     题意: 

                 有一个机器人在x,y坐标系中..它能拿东西的最大重量为C(<=100)...现在机器人和垃圾桶都在原点(0,0)...有N(<=100000)个垃圾在第一象限...机器人只能走曼哈顿距离..并且机器人捡垃圾的顺序要和输入的数序一致...问将所有的垃圾捡到垃圾桶中最短要走多远的距离..

     题解:

                 LRJ大白上的例题...单调队列优化DP..好久没写了..不过还是挺好写的..

                 从LRJ的解析有自己的感悟:

                                              1、状态转移方程可能存在多个..当一个方程列出时间很不现实时..考虑切换角度

                                              2、尝试多几个角度..都无法得到比较ok的状态..那么就要从优化转移上入手...列出方程..仔细观察

                                              3、可用单调队列优化的必要条件:   更新具有范围上的限制...也就是题目中给出了一些限制条件..比如最远距离..最大承重

                                                                                                     方程中可将转移状态以及一些相关参数先行计算不再改变...        

                                                                                                     当先行计算值相等时..后来者必定比先来者更优...也就是有单调性                    

     

Program:

#include<iostream>#include<stdio.h>#include<string.h>#include<cmath>#include<queue>#include<stack>#include<set>#include<algorithm>#define ll long long#define oo 1000000007#define pi acos(-1.0)#define MAXN 100005using namespace std;   struct Robots{       int x,y,w;}R[MAXN];struct node{       int x,f;}myqueue[MAXN*2];int n,C,dp[MAXN],w[MAXN],dis[MAXN],O[MAXN];int main(){             int T,i,cases;        scanf("%d",&T);       for (cases=1;cases<=T;cases++)       {                 scanf("%d%d",&C,&n);                 w[0]=0;                 for (i=1;i<=n;i++)                  {                         scanf("%d%d%d",&R[i].x,&R[i].y,&R[i].w);                         O[i]=R[i].x+R[i].y;                         w[i]=w[i-1]+R[i].w;                 }                 dis[0]=0;                 for (i=1;i<=n;i++) dis[i]=dis[i-1]+(abs(R[i].x-R[i-1].x)+abs(R[i].y-R[i-1].y));                 int head=1,rear=1;                 myqueue[1].x=0,myqueue[1].f=O[1]-dis[1];                 for (i=1;i<=n;i++)                 {                          while (head<=rear && w[i]-w[myqueue[head].x]>C) head++;                         dp[i]=myqueue[head].f+dis[i]+O[i];                         node p;                         p.x=i,p.f=dp[i]-dis[i+1]+O[i+1];                         while (head<=rear && p.f<=myqueue[rear].f) rear--;                         myqueue[++rear]=p;                 }                    if (cases>1) printf("\n");                      printf("%d\n",dp[n]);       }       return 0;}


原创粉丝点击