Fixing the Great Wall UVA - 1336(区间dp)

Fixing the Great Wall

UVA - 1336

题意:修长城,初始位置为fp,n个点要修,初始每个点修缮费用为ci,单位时间增加费用di,问最少费用。

区间dp

和送外卖那个差不多~

有一个细节,输入不加!=EOF的话会超时(虽然题目说了以00结束)

 1 #include <cstdio>
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 const int maxn=1005;
 5 struct node
 6 {
 7     int pos,c,d;
 8     node(int pos=0,int c=0,int d=0):pos(pos),c(c),d(d){}
 9     bool operator <(const node &x) const
10     {
11         return pos<x.pos;
12     }
13 }p[maxn];
14 int sum[maxn];
15 double dp[maxn][maxn][2];
16
17 int main()
18 {
19      int n,v,fp;
20      while(scanf("%d%d%d",&n,&v,&fp)!=EOF&&(n||v||fp))
21      {
22         for(int i=0;i<n;i++)
23             scanf("%d%d%d",&p[i].pos,&p[i].c,&p[i].d);
24         p[n].pos=fp;p[n].c=0;p[n].d=0;
25         sort(p,p+n+1);
26         int w=lower_bound(p,p+n+1,node(fp,0,0))-p;
27         sum[0]=p[0].d;
28         for(int i=1;i<=n;i++) sum[i]=sum[i-1]+p[i].d;
29         //memset(dp,0x3f3f3f3f,sizeof(dp));
30         for(int i=0;i<=n;i++)
31             for(int j=i;j<=n;j++) dp[i][j][0]=dp[i][j][1]=0x3f3f3f3f;
32         dp[w][w][0]=dp[w][w][1]=0;
33         for(int i=w;i>=0;i--)
34             for(int j=w;j<=n;j++)
35         {
36             double ss=sum[i-1]+sum[n]-sum[j];
37             if(i!=0)  //往左
38             {
39                 //从左到左
40                 double t=1.0*(p[i].pos-p[i-1].pos)/v;
41                 dp[i-1][j][0]=min(dp[i-1][j][0],dp[i][j][0]+p[i-1].c+t*ss);
42                 //从右到左
43                 t=1.0*(p[j].pos-p[i-1].pos)/v;
44                 dp[i-1][j][0]=min(dp[i-1][j][0],dp[i][j][1]+p[i-1].c+t*ss);
45             }
46             if(j!=n) //往右
47             {
48                 //从右到右
49                 double t=1.0*(p[j+1].pos-p[j].pos)/v;
50                 dp[i][j+1][1]=min(dp[i][j+1][1],dp[i][j][1]+p[j+1].c+ss*t);
51                 //从左到右
52                 t=1.0*(p[j+1].pos-p[i].pos)/v;
53                 dp[i][j+1][1]=min(dp[i][j+1][1],dp[i][j][0]+p[j+1].c+ss*t);
54             }
55         }
56         int ans=min(dp[0][n][0],dp[0][n][1]);
57         printf("%d\n",ans);
58      }
59      return 0;
60 }

时间: 2024-10-05 21:37:28

Fixing the Great Wall UVA - 1336(区间dp)的相关文章

UVA 10003 区间DP

这个题目蛮有新意的,一度导致我没看透他是区间DP 给一个0-L长度的木板,然后给N个数,表示0-L之间的某个刻度,最后要用刀把每个刻度都切一下 使其断开,然后每次分裂的cost是分裂前的木板的长度.求整个分开之后的最小cost. 当时下意识就想到类似花瓶插花问题,即dp[i][j],表示第i个事物放在第j次动作来的最小代价,但是当我写起来发现很麻烦,我是以刻度点来表示的i,结果发现处理起来相当麻烦,因为实体实际是一块一块的小木板,以点作为转移变量 不仅要加诸多限制,而且加完后发现会互相矛盾,原因

UVa 1630 区间DP Folding

一个字符串如果能简写,要么是重复多次,按题中的要求简写:要么是左右两个部分分别简写后再拼起来. dp(i, j)表示字串(i, j)所能被简写的最短的字符串. 判断一个字符串是否为周期串以及求出它的周期用的KMP算法. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <string> 6 using n

UVA 10891 区间DP+博弈思想

很明显带有博弈的味道.让A-B最大,由于双方都采用最佳策略,在博弈中有一个要求时,让一方的值尽量大.而且由于是序列,所以很容易想到状态dp[i][j],表示序列从i到j.结合博弈中的思想,表示初始状态i->j情况下,先手能获得的最大分数.后手能获得的就是sum[i][j]-dp[i][j].接下来枚举先手选取的是两端的哪一段即可. #include <iostream> #include <cstdio> #include <cstring> using name

uva 10891 区间dp+记忆化搜索

https://vjudge.net/problem/UVA-10891 给定一个序列x,A和B依次取数,规则是每次只能从头或者尾部取走若干个数,A和B采取的策略使得自己取出的数尽量和最大,A是先手,求最后A-B的得分. 令 f(i,j)表示对于[i,j]对应的序列,先手可以从中获得的最大得分,那么答案可以写为  f(i,j)-(sum(i,j)-f(i,j)),也就是 2*f(i,j)-sum(i,j) 下面讨论f(i,j)的写法,显然递归的形式更好表达一些,为了防止重复的计算使用记忆化搜索.

UVA-1336 Fixing the Great Wall(区间DP)

题目大意:长城(视作x正半轴)有n处破损.有一个智能修复机器人,它的初始位置和移动速度已知.每处破损处都有一组参数(x,c,d),x表示位置,c.d表示在时间t后再修复该处破损的花费为d*t+c.求用一个机器人修复所有破损的最小花费. 题目分析:要想最终代价最低,就不能跳跃着修复,也就是经过一段时间后已经修复好的破损应是一段连续区间.定义dp(i,j,k)表示修好(i,j)后机器人停留在k(0表示在左端,1表示在右端)端的费用.修复某处破损的代价虽然不是定值,但却是随着时间线性增长的,所以当修复

【暑假】[深入动态规划]UVa 10618 Fixing the Great Wall

UVa 10618 Fixing the Great Wall 题目:  http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36139 思路:   数轴上有n个点需要修复,每个点有信息c,x,d 表示位于x且在t时修缮的费用是c+d*t,找一个修缮序列使n个点能全部修缮且有费用最小. 可以发现:在任意时刻,修缮完的点都是连续的,因为修缮不需要时间,将一些点“顺手”修缮了肯定不差. d[i][j][k],表示已经将i-j个点修缮

uva 10003 Cutting Sticks 简单区间dp

// uva 10003 Cutting Sticks 区间dp // 经典的区间dp // dp(i,j)表示切割小木棍i-j所需要的最小花费 // 则状态转移为dp(i,j) = min{dp(i,k) + dp(k,j) + a[j]-a[i]) // 其中k>i && k<j // a[j] - a[i] 为第一刀切割的代价 // a[0] = 0,a[n+1] = L; // dp数组初始化的时候dp[i][i+1]的值为 0,这表示 // 每一段都已经是切割了的,不

uva live 3516 Exploring Pyramids 区间DP

// uva live 3516 Exploring Pyramids 区间DP // // 题目大意: // // 给你一个多叉树,每个节点是一个大写字母,从根节点走,按照先序遍历的 // 原则访问,不能访问则回溯,每次记录一下节点的字符,最后得到一个字符串.现 // 在给你一个字符串,问可能符合条件的多叉树的数量. // // 解题思路: // // 区间DP,我们注意到,从根节点出发,一定会再次回到根节点,那么我们可以设 // d(i,j) 是序列i到j段形成的符合条件的多叉树的数量,则

UVA 10003 Cutting Sticks(区间dp)

Description  Cutting Sticks  You have to cut a wood stick into pieces. The most affordable company, The Analog Cutting Machinery, Inc. (ACM), charges money according to the length of the stick being cut. Their procedure of work requires that they onl