UVA 10201 Adventures in Moving - Part IV(动态规划)
来源:互联网 发布:mac运行32位软件 编辑:程序博客网 时间:2024/06/05 03:15
UVA 10201 Adventures in Moving - Part IV(动态规划)
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1142
题意:
有一辆车,原始装有100L汽油,到达距离为d的目的地,中间有x个加油站,每升油的价格为p。汽车每跑一公里耗油1L,求到达目的地油箱仍然有100L的最小花费。
分析:
这道题目真是醉了,DP不难,但是细节太多了。
本题一看有点类似于01背包问题。首先我们要知道如何定义一辆车的状态?
一辆车的状态只与(它当前所在的加油站编号,它当前还剩多少油)这两个因素有关,所以我们如下定义dp状态:
dp[i][j]==x表示车正好刚走过第i个加油站后(可能在i站加了油,也可能没有)且还剩j升油时 花费的最小费用为x。
初始状态dp全为INF,且dp[0][100]=0.
假设车在第i个站加了k升油之后具有j升油 (k>=0) ,那么有下面的状态转移公式:(w为dist[i]-dist[i-1]的值,即w是从上一站走到下一站的距离)
dp[i][j] = min( dp[i][ j ] , dp[i-1][j+w-k ]+k*p[i] )
最终我们所求为dp[n][100]的值。
本题不能用的滚动数组。
注意由于油箱容量为200,所以任何时刻油量都不能超过200.令 w为dist[i]-dist[i-1]的值(即w是从上一站走到下一站的距离)。有下面几种情况需要注意:
1. 状态j的枚举为[0,200]范围。
2. 假设车在第i个站加了k升油之后具有j升油,那么车刚到i站时有j-k升油且车离开i-1站的那一刻有j-k+w升油。这里需要注意的是 k<=j且 j-k<=200 且j-k+w<=200。
3. 当车最后到达第n个站时,并不代表它到了终点。可能还需要走一段距离,这时候需要看这段距离x+100保存油量是否<=200,且还要看dp[n][100+x]是否<INF?(想想为什么)
4. 初始距离就大于目的距离的站点不用考虑。因为走不到那么远。
5. 由于输入没有结束标志,只能处理每行字符串,所以这里很容易出错。
AC代码:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define INF 1e9int n;int dp[100+5][200+5];int dist[100+5];//第i个站的距离int p[100+5]; //第i个站的价格int len;int main(){ char str[100]; gets(str); //读数据组数 int T; sscanf(str,"%d",&T); gets(str);//读空行 for(int kase=1;kase<=T;kase++) { if(kase>1) printf("\n");//空行 //读输入数据 dist[0]=0; n=0; gets(str); sscanf(str,"%d",&len); while(gets(str)) { if(str[0]=='\0') break; n++; sscanf(str,"%d %d",&dist[n],&p[n]); if(dist[n]>len) n--;//距离大于目的距离的站不用考虑 } //初始化 for(int i=0;i<=n;i++) for(int j=0;j<=200;j++) dp[i][j]=INF; dp[0][100]=0; //DP递推过程 for(int i=1; i<=n; i++) { int w=dist[i]-dist[i-1];//第i站与第i-1站的距离差值 for(int j=0; j<=200; j++) { for(int k=0; k<=j; k++) if(j+w-k<=200 )//&& dp[i-1][j+w-k]!=INF { dp[i][j]=min(dp[i][j], dp[i-1][j+w-k]+k*p[i]); } } } //打印结果 if(len-dist[n]>100 || dp[n][100+len-dist[n]]==INF) printf("Impossible\n"); else printf("%d\n",dp[n][100+len-dist[n]]); } return 0;}
- UVA 10201 Adventures in Moving - Part IV(动态规划)
- uva 10201 Adventures in Moving - Part IV
- UVA 10201 Adventures in Moving - Part IV
- UVA 10201 Adventures in Moving - Part IV
- UVA 10201 Adventures in Moving - Part IV
- uva 10201 Adventures in Moving - Part IV
- UVA - 10201 Adventures in Moving - Part IV
- uva 10201 - Adventures in Moving - Part IV
- UVA - 10201 Adventures in Moving - Part IV
- UVA - 10201 Adventures in Moving - Part IV
- UVA - 10201 Adventures in Moving - Part IV
- uva 10201 Adventures in Moving - Part IV
- uva--UVA 10201Adventures in Moving - Part IV
- Adventures in Moving - Part IV+uva+dp
- UVA 10201 Adventures in Moving - Part IV(dp)
- uva 10201 - Adventures in Moving - Part IV(dp)
- UVA 10201 Adventures in Moving - Part IV 车站加油 dp
- Adventures in Moving - Part IV - UVa 10201 dp
- VS2010与mysql
- STL源码之实现一个简易的Vector容器
- Dongle烧写模块重构(四)--用工厂模式将方案商从功能代码中抽离
- servlet 学习二
- OllyDbg破解系列学习笔记(四)
- UVA 10201 Adventures in Moving - Part IV(动态规划)
- 检测TCP端口占用状态的函数
- ASP.NET MVC3开发 - CodeFisrt数据库篇之M层验证之调用远程方法(Remote)验证
- 用fork函数,由一个父进程生成两个子进程
- 1279 验证角谷猜想
- Servlet杂记
- ASP.NET MVC3开发-数据库篇之CodeFisrt开发(一)
- memcached ,redis 在windows下以服务方式运行
- 检测UDP端口占用状态的函数