Time Limit: 3 second
Memory Limit: 2 MB
【问题描述】
某条街上每一公里就有一汽车站,乘车费用如下表:公里数 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
费用 | 12 | 21 | 31 | 40 | 49 | 58 | 69 | 79 | 90 | 101 |
而一辆汽车从不行驶超过10公里。某人想行驶n公里,假设他可以任意次换车,请你帮他找到一种乘车方案使费用最小(10公里的费用比1公里小的情况是允许的)。
【输入格式】
第一行为10个不超过100的整数,依次表示行驶1~10公里的费用,相邻两数间用空格隔开。第二行为某人想要行驶的公里数。
【输出格式】
仅一行,包含一个整数,表示该测试点的最小费用。
【输入样例】
12 21 31 40 49 58 69 79 90 101 15
【输出样例】
147
【题解】
设f[j]表示到j公里处,所需的最小花费。
f[j] = min (f[j],f[j-i] + cost[i]),i是公里数(1..10),cost[i]表示走i公里的花费。
即如果更新了f[j],则从f[j-i]处进行一次换车。
这很像背包问题。
到了第5公里,前4公里的最优值就与第1公里的无关了,而第5公里的最优值可以由前面的最优值推出。
一开始所有的f值都为一个很大的数,除了f[0]外。f[0] = 0表示走0公里不要花费。
【代码】
#include <cstdio> int cost[11],f[100000],m; void input_data() { for (int i = 1;i <= 10;i++) scanf("%d",&cost[i]); scanf("%d",&m); } void get_ans() { for (int i = 1;i <= m;i++) //一开始所有值都赋成一个很大的值。 f[i] = 2100000000/3; f[0] = 0; //走0公里花费为0; for (int j = 1;j <= m;j++) //对m公里的路进行DP(动态规划是一个动词 嗯。。) for (int k = 1;k <= 10;k++) { if (j - k < 0) break; //如果未满10公里 则要break掉。后面k //越来越大所以可以break掉.break只break一层循环 if (f[j] > f[j-k] + cost[k]) f[j] = f[j-k] + cost[k]; } } void output_ans() { printf("%d",f[m]); } int main() { //freopen("F:\rush.txt","r",stdin); input_data(); get_ans(); output_ans(); return 0; }