UVALive3181(区间DP)
2016-03-08 16:30
239 查看
大概题意:给自己所在位置和自己的速度,再给n个破损点让你去修复,给每个点修复好所需要的固定费用和迟到一秒修复的额外费用,求修复完所有点所需要的最小费用。
思路:熟悉的话,一看就大概知道这个用区间DP了。固定费用是固定的,就暂时不算(以后加上),就先想办法把那些额外费用降到最低。因为答案要求输出整数,但是计算过程又因为速度问题会出现小数,所以就先假设速度为1,到时再清算。dp[i][j][0]表示修复i点到j点,自己在i点的时候,所有点因为拖延所增加的额外费用(所有,就是包括已经修复的和未修复的,以假设速度为1为前提)。dp[i][j][1]表示修复了i点到j点,自己在j点的时候,所有点因为拖延所增加的额外费用。那么额外费用就是dp[1]
[0], dp[1]
[1]的最小值再除以速度。代码大概步骤:将起点也加入这n个点,然后n++,然后将所有点按位置排序,找到起点新位置pos2,将dp数组全部初始化INF(很大的值),然后dp[pos2][pos2][1]=dp[pos2][pos2][0]=0,然后区间DP。
思路:熟悉的话,一看就大概知道这个用区间DP了。固定费用是固定的,就暂时不算(以后加上),就先想办法把那些额外费用降到最低。因为答案要求输出整数,但是计算过程又因为速度问题会出现小数,所以就先假设速度为1,到时再清算。dp[i][j][0]表示修复i点到j点,自己在i点的时候,所有点因为拖延所增加的额外费用(所有,就是包括已经修复的和未修复的,以假设速度为1为前提)。dp[i][j][1]表示修复了i点到j点,自己在j点的时候,所有点因为拖延所增加的额外费用。那么额外费用就是dp[1]
[0], dp[1]
[1]的最小值再除以速度。代码大概步骤:将起点也加入这n个点,然后n++,然后将所有点按位置排序,找到起点新位置pos2,将dp数组全部初始化INF(很大的值),然后dp[pos2][pos2][1]=dp[pos2][pos2][0]=0,然后区间DP。
#include <iostream> #include <stdio.h> #include <algorithm> using namespace std; const long long INF=20000000000000000,N=1010; long long dp[N][N][2],sum[N]; struct kk{ long long pos,c; }e[N]; bool cmp(const kk & x,const kk &y){ return x.pos<y.pos; } int main() { long long n,v,x,p,c,cc; while(scanf("%lld%lld%lld",&n,&v,&x)==3){ if(n==0&&v==0&&x==0) break; long long ans=0; for(int i=1;i<=n;i++){ scanf("%I64d%I64d%I64d",&p,&c,&cc); ans=ans+c*v; e[i].pos=p,e[i].c=cc; } e[n+1].pos=x,e[n+1].c=0; n++; sort(e+1,e+1+n,cmp); int pos2; for(int i=1;i<=n;i++){ if(e[i].pos==x){ pos2=i; } } sum[0]=0; for(int i=1;i<=n;i++) sum[i]=sum[i-1]+e[i].c; //sum 记录了从1到n点 for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ for(int k=0;k<=1;k++) dp[i][j][k]=INF; } } dp[pos2][pos2][1]=dp[pos2][pos2][0]=0; for(int len=2;len<=n;len++){ //从小区间开始,len表示区间长度 for(int i=1;i<=n;i++){ //i是区间起点 int j=i+len-1; //j是区间终点 if(j>n) continue; if(i<=pos2&&j>=pos2){ //pos2是起点的位置,肯定在的,如果不包含起点的区间就不用看了 dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][0]+(e[i+1].pos-e[i].pos)*(sum[n]-sum[j]+sum[i])); dp[i][j][0]=min(dp[i][j][0],dp[i+1][j][1]+(e[j].pos-e[i].pos)*(sum[n]-sum[j]+sum[i])); dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][0]+(e[j].pos-e[i].pos)*(sum[n]-sum[j-1]+sum[i-1])); dp[i][j][1]=min(dp[i][j][1],dp[i][j-1][1]+(e[j].pos-e[j-1].pos)*(sum[n]-sum[j-1]+sum[i-1])); dp[i][j][1]=min(dp[i][j][1],dp[i][j][0]+(e[j].pos-e[i].pos)*(sum[n]-sum[j]+sum[i-1])); dp[i][j][0]=min(dp[i][j][0],dp[i][j][1]+(e[j].pos-e[i].pos)*(sum[n]-sum[j]+sum[i-1])); } } } long long ans2=min(dp[1][n][1],dp[1][n][0]); ans2=ans2+ans; ans2=ans2/v; printf("%lld\n",ans2); } return 0; }
相关文章推荐
- 顺序容器
- Android studio gradle 配置
- 代码托管服务器比较
- 算法系列(1)排序算法
- 共同学习Java源码--常用数据类型--String(一)
- Android App整体架构设计的思考
- Redis入门很简单之六【Jedis常见操作】
- oracle登录时会报错 initialization error
- Atitit.json xml 序列化循环引用解决方案json
- 万恶DevExpress
- dedecms怎么给第一个li加class
- 记录 yii GridView 默认搜索条件
- Atitit.json xml 序列化循环引用解决方案json
- Android Fragment 你应该知道的一切
- 共同学习Java源码--开篇语
- 获取imageview里的Bitmap
- 从google的DrawerLayout来看看scroller的使用方法
- Hack
- 管理口令(P):[INS-30011] 输入的 ADMIN 口令不符合 Oracle 建议的标准
- centos redhat 安装g++