• UVA3983 Robotruck 题解


    题目描述

    有n个垃圾,第i个垃圾的坐标为(xi,yi),重量为wi。有一个机器人,要按照编号从小到大的顺序捡起所有垃圾并扔进垃圾桶(垃圾桶在原点(0,0))。机器人可以捡起几个垃圾以后一起扔掉,但任何时候其手中的垃圾总重量不能超过最大载重C。两点间的行走距离为曼哈顿距离(即横坐标之差的绝对值加上纵坐标之差的绝对值)。求出机器人行走的最短总路程(一开始,机器人在(0,0)处)。

    输入格式:

    输入的第一行为数据组数T(1<=T<=15),每组数据的第一行为最大承重C(1<=C<=100);第二行为正整数n(1<=n<=100000),即垃圾的数量;一下n行每行为三个非负整数x,y,w,即坐标和重量(重量保证不超过C)。

    输出格式:

    对于每组数据,输出总路径的总长度。

    又是一道单调队列优化的DP。按照这种题目的一般解决过程,我们应当先写出暴力DP的状态转移方程,然后再针对其方程的特点选择合适的优化方式进行优化。

    先前缀和预处理一下吧,有什么用往下看就知道了。我们用s[i]表示1--i个垃圾的总重量,step[i]表示1--i的总路程长度(不回垃圾桶处)。

    然后,我们设f[i]表示捡了第i个垃圾并回到垃圾桶的最短的总路程的长度,那么对于每一个i,我们枚举j(1<=j<=i&&s[i]-s[j-1]<=C),意为“捡完1--j-1的全部垃圾回到垃圾桶后,再出发一次性捡完j--i的所有垃圾”,其中s[i]-s[j-1]<=C是因为机器人所捡垃圾重量不能超过他的最大载重。

    那么状态转移方程是什么呢?显然,捡完1--j-1的全部垃圾并回到垃圾桶处后,机器人必须先得到达j点,然后一步一步走到i点,最后再走回原点,分为三段,所以状态转移方程就显而易见了:

    \[f[i]=min(f[j-1]+x[j]+y[j]+step[i]-step[j]+x[i]+y[i])(1<=j<=i且s[i]-s[j-1]<=C) \]

    由于i在当下是固定的,所以(step[i]+x[i]+y[i])的值也是固定的,那么想要所取的值最小,就是要(f[j-1]+x[j]+y[j]-step[j])的值最小。对于维护最小值的事,当然要请来单调队列啦,我们设x=f[j-1]+x[j]+y[j]-step[j],将x与单调队列的队尾元素的值进行比较,取较小的那一个。同时,队首j也要及时判断是否满足(s[i]-s[j-1]<=C),不满足即出队。

    代码如下:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int T,C,n,x[100001],y[100001],w[100001];
    long long s[100001],step[100001],f[100001],q[100001],p[100001],head,tail,k;
    int main()
    {
    	scanf("%d",&T);
    	for(register int i=1;i<=T;i+=1)
    	{
    		scanf("%d",&C);
    		scanf("%d",&n);
    		for(register int i=1;i<=n;i+=1)
    		{
    			scanf("%d%d%d",&x[i],&y[i],&w[i]);
    			s[i]=s[i-1]+w[i];
    			step[i]=step[i-1]+abs(x[i]-x[i-1])+abs(y[i]-y[i-1]);
    		}
    		head=1;tail=0;
    		for(register int i=1;i<=n;i+=1)
    		{
    			k=f[i-1]+x[i]+y[i]-step[i];
    			while(head<=tail&&p[tail]>=k)tail--;
    			q[++tail]=i;
    			p[tail]=k;
    			while(head<=tail&&s[i]-s[q[head]-1]>C)head++;
    			f[i]=p[head]+step[i]+x[i]+y[i];
    		}
    		printf("%lld\n",f[n]);
    		if(i!=T)printf("\n");
    	}
    	return 0;
    }
    
  • 相关阅读:
    linux 查询文件在多个目录里面,只保留一个
    mysql 定时备份
    mysql 赋予权限报错Column count of mysql.user is wrong. Expected 45, found 43. The table is probably corrupted
    Mysql 启动报错Error: page 5 log sequence number 2580579963
    docker 限制日志文件大小和数量
    docker 安装
    MVC3学习第十五章 武林外传大结局
    MVC3学习第十四章 佟掌柜第三弹——MVC3下利用陕北吴旗娃的验证码控件实现验证码功能以及在mvc3下使用编辑器
    MVC3学习第十三章 佟掌柜第二弹——MVC3下利用陕北吴旗娃的分页控件实现数据分页
    MVC3学习第十二章 佟掌柜第一弹----利用MVC3实现用户的注册登录和了解MVC中的分部视图、用户控件
  • 原文地址:https://www.cnblogs.com/ForwardFuture/p/9022059.html
Copyright © 2020-2023  润新知