题目描述:
在某条线路上有N个火车站,有三种距离的路程,L1,L2,L3,对应的价格为C1,C2,C3.其对应关系如下:
距离s           票价
0<S<=L1         C1
L1<S<=L2        C2
L2<S<=L3        C3
输入保证0<L1<L2<L3<10^9,0<C1<C2<C3<10^9。
每两个站之间的距离不超过L3。
当乘客要移动的两个站的距离大于L3的时候,可以选择从中间一个站下车,然后买票再上车,所以乘客整个过程中至少会买两张票。
现在给你一个 L1,L2,L3,C1,C2,C3。然后是A B的值,其分别为乘客旅程的起始站和终点站。
然后输入N,N为该线路上的总的火车站数目,然后输入N-1个整数,分别代表从该线路上的第一个站,到第2个站,第3个站,……,第N个站的距离。
根据输入,输出乘客从A到B站的最小花费。
输入:
以如下格式输入数据:
L1  L2  L3  C1  C2  C3
A  B
N
a[2]
a[3]
……
a[N]
输出:
可能有多组测试数据,对于每一组数据,
根据输入,输出乘客从A到B站的最小花费。
样例输入:
1 2 3 1 2 3
1 2
2
2
样例输出:
2

这道题真是一个惨痛的回忆。
开始的思路是普通的动态规划思路,即经典的分割问题,最后通过的代码如下
 #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#define MAX 300
#define inf 10000000009 long long minCost[MAX][MAX];
long long dis[MAX][MAX];
long long dis0[MAX]; int main(int argc, char const *argv[])
{
long long L1, L2, L3, C1, C2, C3;
//freopen("input.txt","r",stdin);
while(scanf("%lld %lld %lld %lld %lld %lld",&L1, &L2, &L3, &C1, &C2, &C3) != EOF)
{
int A, B;
int N;
scanf("%d %d",&A,&B);
scanf("%d",&N);
dis0[] = ;
for(int i = ; i <= N; i++) {
scanf("%lld",&dis0[i]);
}
for(int l = ; l <= N - ; l++) {
//length from 1 to N - 1
for(int i = ; i <= N - l; i++) {
//start from i to N - l
int j = i + l;
//end is i + l
dis[i][j] = dis0[j] - dis0[i];
if(dis[i][j] <= L1) {
minCost[i][j] = C1;
}
else if(dis[i][j] <= L2) {
minCost[i][j] = C2;
}
else if(dis[i][j] <= L3) {
minCost[i][j] = C3;
}
else {
minCost[i][j] = inf;
} for(int k = i + ; k <= j-; k++) {
long long int q = minCost[i][k] + minCost[k][j];
if(q < minCost[i][j]) {
minCost[i][j] = q;
}
}
}
}
if(A < B) {
printf("%lld\n",minCost[A][B]);
}
else if(A > B){
printf("%lld\n",minCost[B][A]);
}
else {
printf("%d\n",);
} }
return ;
}

但代码一开始提交了n次都没有通过,经过很长时间的排查,终于发现了原因。一开始我设的inf是

1000000009,WA改成了

10000000009后就AC了。

之后我发现没必要去算出每两个点之间的最小花费,只需要计算出从A到B之间的最小花费即可,dis数组也不需要

代码如下:

 #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#define MAX 300
#define inf 10000000009 long long minCost[MAX][MAX];
long long dis0[MAX]; int main(int argc, char const *argv[])
{
long long L1, L2, L3, C1, C2, C3;
//freopen("input.txt","r",stdin);
while(scanf("%lld %lld %lld %lld %lld %lld",&L1, &L2, &L3, &C1, &C2, &C3) != EOF)
{
int A, B;
int N;
scanf("%d %d",&A,&B);
scanf("%d",&N); for(int i = ; i <= N; i++) {
scanf("%lld",&dis0[i]);
}
if(A > B) {
int temp = A;
A = B;
B = temp;
}
long long n = B - A;
dis0[] = ;
minCost[A][A] = ;
for(int l = ; l <= n; l++) {
//length from 1 to N - 1
for(int i = A; i <= A + n - l; i++) {
//start from i to N - l
int j = i + l;
//end is i + l
long long temp = dis0[j] - dis0[i];
if(temp <= L1) {
minCost[i][j] = C1;
}
else if(temp <= L2) {
minCost[i][j] = C2;
}
else if(temp <= L3) {
minCost[i][j] = C3;
}
else {
minCost[i][j] = inf;
} for(int k = i + ; k <= j-; k++) {
long long int q = minCost[i][k] + minCost[k][j];
if(q < minCost[i][j]) {
minCost[i][j] = q;
}
}
}
}
printf("%lld\n",minCost[A][B]); }
return ;
}

但是我们研究一下会发现,如果两地的距离小于L3,则它们之间的最小花费必然在C1,C2,C3之间,所以若将minCost改为一维数组,将i作为中间点,j作为终点,当i到j的距离小于L3时,minCost[j] = min (minCost[j], minCost[i] + Ci); 所以遍历i时,选取与其距离小于L3的j,即可。代码如下:

 #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#define MAX 150
#define inf 10000000009 long long minCost[MAX];
long long dis0[MAX]; int main(int argc, char const *argv[])
{
long long L1, L2, L3, C1, C2, C3;
//freopen("input.txt","r",stdin);
while(scanf("%lld %lld %lld %lld %lld %lld",&L1, &L2, &L3, &C1, &C2, &C3) != EOF)
{
int A, B;
int N; scanf("%d %d",&A,&B);
scanf("%d",&N);
dis0[] = ;
for(int i = ; i <= N; i++) {
scanf("%lld",&dis0[i]);
minCost[i] = inf;
}
if(A > B) {
int temp = A;
A = B;
B = temp;
}
minCost[A] = ;
for(int i = A; i < B; i++) {
for(int j = i + ; j <= B; j++) {
long long int temp;
if(dis0[j] - dis0[i] <= L1) {
temp = C1;
}
else if(dis0[j] - dis0[i] <= L2) {
temp = C2;
}
else if(dis0[j] - dis0[i] <= L3) {
temp = C3;
}
else {
break;
}
long long q = minCost[i] + temp;
if(minCost[j] > q) {
minCost[j] = q;
}
}
}
printf("%lld\n",minCost[B]);
}
return ;
}

因为两个站的最大距离不超过L3,所以从A站到j站,中间必然会经过距离j站距离小于L3的某站,故minCost[j]在遍历时中间的分割点必然在这些站之间,所以可以这样化简

九度oj 题目1086:最小花费的更多相关文章

  1. 九度oj题目&amp;吉大考研11年机试题全解

    九度oj题目(吉大考研11年机试题全解) 吉大考研机试2011年题目: 题目一(jobdu1105:字符串的反码).    http://ac.jobdu.com/problem.php?pid=11 ...

  2. 九度oj 题目1007:奥运排序问题

    九度oj 题目1007:奥运排序问题   恢复 题目描述: 按要求,给国家进行排名. 输入:                        有多组数据. 第一行给出国家数N,要求排名的国家数M,国家号 ...

  3. 九度OJ 题目1384:二维数组中的查找

    /********************************* * 日期:2013-10-11 * 作者:SJF0115 * 题号: 九度OJ 题目1384:二维数组中的查找 * 来源:http ...

  4. hdu 1284 关于钱币兑换的一系列问题 九度oj 题目1408:吃豆机器人

    钱币兑换问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  5. 九度OJ 1502 最大值最小化(JAVA)

    题目1502:最大值最小化(二分答案) 九度OJ Java import java.util.Scanner; public class Main { public static int max(in ...

  6. 九度oj 题目1087:约数的个数

    题目链接:http://ac.jobdu.com/problem.php?pid=1087 题目描述: 输入n个整数,依次输出每个数的约数的个数 输入: 输入的第一行为N,即数组的个数(N<=1 ...

  7. 九度OJ题目1105:字符串的反码

    tips:scanf,cin输入字符串遇到空格就停止,所以想输入一行字符并保留最后的"\0"还是用gets()函数比较好,九度OJ真操蛋,true?没有这个关键字,还是用1吧,还是 ...

  8. 九度oj题目1009:二叉搜索树

    题目描述: 判断两序列是否为同一二叉搜索树序列 输入:                        开始一个数n,(1<=n<=20) 表示有n个需要判断,n= 0 的时候输入结束. 接 ...

  9. 九度oj题目1002:Grading

    //不是说C语言就是C++的子集么,为毛printf在九度OJ上不能通过编译,abs还不支持参数为整型的abs()重载 //C++比较正确的做法是#include<cmath.h>,cou ...

随机推荐

  1. 什么是OOA/OOD

    Object Oriented Analyzing Object Oriented Design Object Oriented Programming ooa(object oriented ana ...

  2. Solr6+IKAnalyzer分词环境搭建

    环境要求 Zookeeper版本:zookeeper-3.4.8 JDK版本: jdk1.8. Solr版本:solr-6.4.1 Tomcat版本:tomcat8 ZK地址:127.0.0.1:21 ...

  3. 《深入理解JavaScript闭包和原型》笔记

    By XFE-堪玉 以下知识来源于对王福朋所写<深入理解javascript原型和闭包>的理解和整理 一切都是对象[引用类型],对象都是通过函数创建的[Funcion类型] 对象是属性的集 ...

  4. bin&sbin 命令作用

    最近需要了解sbin与bin的功能,需要整理一下.一下全部为Ubuntu14里面默认安装的.在这里收集一下,转载请注明出处! bin bash shell bunzip2 .bz2文件的解压缩程序. ...

  5. 关于&0xF0的一些认识

    首先,要明白0xF0转换成二进制是多少 ----- 1111 0000(0xF0相当于高四位保留,低四位置为0) 我们拿麻将的一万(0x01).一条(0x11).一筒(0x21) 一万的二进制原码   ...

  6. activeandroid复制本地数据库问题总结

    activeandroid no such table 解决activeandroid no such table failed to read row 0 column 1 from a curso ...

  7. Fedora19添加和设置YUM源

    Fedora19添加和设置YUM源添加yum源前先安装fastestmirror/downloadonly插件和axelget插件: 1.安装fastestmirror/downloadonly插件 ...

  8. 机器学习之-奇异值分解(SVD)原理详解及推导

    转载 http://blog.csdn.net/zhongkejingwang/article/details/43053513 在网上看到有很多文章介绍SVD的,讲的也都不错,但是感觉还是有需要补充 ...

  9. Higher level thinking

    「Higher level thinking」-- 出自 Ray Dalio 的<Principles>(PDF 原文:Principles by Ray Dalio) Higher le ...

  10. android stuido ndk 开发

    开发环境: Android studio 1.0.2 ndk android-ndk-r10d-windows-x86_64 ------------------------------------ ...