zoj 3469
来源:互联网 发布:paper.js中文文档 编辑:程序博客网 时间:2024/06/16 17:57
转自:http://www.2cto.com/kf/201207/142419.html
题目大意:送餐员送餐问题。有n个人叫餐,每个人都在x轴上,并且每个人都有个坑爹度(和等餐时间有关,据说顾客认为坑爹值到一定程度他的小宇宙就要爆发).现在送餐员从x轴上的某点出发,路上奔跑速度是v,要一次性把所有餐送完。叫餐的人得到餐的时间和顺序不同,坑爹度总和也就不同。合格的送餐员要让客户体验最好,请问最少坑爹度和为多少
解题思路:下午开了2011年浙大2月份的月赛,做了三题,这题没出,被虐暴了。这题要考虑当前状态对后续状态的影响,相当经典,很锻炼思维,这种题目我喜欢。
先说下本题的模型,送餐的顺序是一个从x位置开始的从1...n的一个全排列,我们要做的是找一个全排列它的总坑爹值最小。
现在设想已经找到几个点相对位置是 3 2 1 x 4 5 6,使坑爹值小的策略是先送中间的再往两边送,因为送完中间的可以顺着去送两边。
如果已经计算好了x 1 4的最小坑爹值,如果不考虑坑爹值最小这个条件我们先找2或者5是不是都可以?选了以后对之前的状态不会影响,因为后面的时间影响不到前面的。得出一个结论,本模型无后效性。
确定了无后效性,那就要考虑那个约束条件和状态,我们的决策是在x两边来回选择坑爹值小的,那么设dp[i][j][k]表示从第i个人到第j个人都已经送完餐最后停在k== 0 - 》左边,k == 1 -》右边的最小坑爹值。
状态明确了转移也就睡到渠成了。dp[i][j][0] 可能从dp[i+1][j][0],dp[i+1][j][1] (i+1在i右边,两个都在i左边)转移而来,dp[i][j][1]可能从dp[i][j-1][0],dp[i][j-1][1]转移而来。具体状态转移方程参见代码,很容易看懂。
然后特别要注意的是每转移一次,都会增加一定的时间,水涨船高,后面的人拿到餐的时间也晚了,也就是说必须把对后面的影响考虑在当前状态下,并且对后面的每个人影响都是一样的,那么当前转移用时t,后面还有x人,当前的状态就要多加x*t,
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[1005][1005][2];
const int inf = 1000000000;
struct Node
{
int x;
int v;
};
Node node[1005];
int sum[1005];
bool cmp(const Node &n1,const Node &n2)
{
return n1.x<n2.x;
}
int getDelay(int i,int j)
{
if(i>j)
return 0;
return sum[j]-sum[i-1];
}
int DP(int n,int x)
{
int res;
for(int i = 1;i<=n;i++)
if(node[i].x==x)
{
res = i;
break;
}
for(int i = 1;i<=n;i++)
for(int j = 1;j<=n;j++)
dp[i][j][0] = dp[i][j][1] = inf;
dp[res][res][0] = dp[res][res][1] = 0;
for(int i = res;i>=1;i--)
for(int j = res;j<=n;j++)
{
if(i==j)
continue;
int delay = getDelay(1,i-1)+getDelay(j+1,n);
dp[i][j][0] = min(dp[i][j][0],dp[i+1][j][1]+(delay+node[i].v)*(node[j].x-node[i].x));
dp[i][j][0] = min(dp[i][j][0],dp[i+1][j][0]+(delay+node[i].v)*(node[i+1].x-node[i].x));
dp[i][j][1] = min(dp[i][j][1],dp[i][j-1][0]+(delay+node[j].v)*(node[j].x-node[i].x));
dp[i][j][1] = min(dp[i][j][1],dp[i][j-1][1]+(delay+node[j].v)*(node[j].x-node[j-1].x));
}
return min(dp[1][n][1],dp[1][n][0]);
}
int main()
{
int n,x,v;
while(scanf("%d %d %d",&n,&v,&x)!=EOF)
{
for(int i = 1;i<=n;i++)
{
scanf("%d %d",&node[i].x,&node[i].v);
}
node[++n].x = x;
node[n].v = 0;
sort(node+1,node+n+1,cmp);
for(int i = 1;i<=n;i++)
{
sum[i] = sum[i-1]+node[i].v;
}
int ans = DP(n,x);
printf("%d\n",ans*v);
}
}
- zoj 3469
- Food Delivery zoj 3469
- ZOJ 3469 Food Delivery
- ZOJ 3469 区间dp
- zoj 3469 区间dp
- ZOJ 3469 Food Delivery
- ZOJ 3469 Food Delivery
- ZOJ 3469(区间DP)
- ZOJ-3469 Food Delivery
- ZOJ 3469 区间DP
- ZOJ 3469 Food Delivery
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- 看懂信息检索和网络数据挖掘领域论文的必备知识总结
- linux中根据文件内容关键字,搜索文件
- 在linux 部署项目
- 第62天的交易(2013-7-2)(-100)(32.29)
- 决策树完结篇
- zoj 3469
- 低功耗设备在使用纽扣电池时需要注意电压、电流变化
- 排名
- Software defined storage
- DrawerLayout打开和关闭时禁止刷新ActionBar
- 判断三角形类型
- opengl解引用数组出错
- 基于live555的视频直播 DM368IPNC RTSP分析
- 开机后将sim/uim卡上的联系人写入数据库