NKOJ P1001 最小乘车费用 题解

前言

这个系列是我和我的同学一起写的,收录了NKOJ的部分题目的题解,用不断更,NK的同学们可以借鉴学习一下,其他学信竞的也可以看一下,刷新一下题库。总帖在这里
点个赞再看叭~

题目

问题描述

某条街上每一公里就有一汽车站,乘车费用如下表:
公里 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公里的费用,相邻两数间用空格隔开;
第二行为某人想要行驶的公里数(1~100公里)。

输出格式

输出文件仅一行包含一个整数,表示该测试点的最小费用

样例输入

12 21 31 40 49 58 69 79 90 101
15

样例输出

147

题解

动态规划(dp)

这道题的正解肯定是动规,当然我会讲一点不是正解的东西…
OK啊不瞎扯了先看动归解法好吧。
知周所众,做动规题的第一步是什么?没错,聪明如你,肯定是输入啊!
(你别说我还真忘过写输入)

输入

这道题他没有单独标注数据范围,但是它说了, 公里数为1~100公里,所以我们的数组要开到100。
(好习惯:开数组不要题目说多大就开多大,在空间允许的情况下,尽量能比数据范围大出10左右)

输入代码如下:

int main() {
	for(int i=1;i<=10;i++){
			scanf("%d",&f[i]);
		}
	scanf("%d",&n);
}

状态转移方程

知周所众,做动规题的第二步是什么?(这次真没坑)没错,聪明如你,就是把状态转移方程写出来!
状态转移方程是动规的一大难点,只要把这点搞懂,你就离AC只有一步之遥了。
状态转移状态转移,首先你得给这道题定义一个状态。
这道题是“某人”想坐n公里车,求最小的乘车费用,那么可不可以把“某人”坐到每一个站的费用定义成一个状态,然后从前往后递推处理出第n个站的费用呢?答案是:可以的。
那么定义好状态就好办了,想想怎么把一个状态转移成另一个状态。那么既然状态是做到某一个站的费用,那么转移状态就是用一个站的费用推出下一个站的费用呗。
那么由此,就可以列出状态转移方程:dp[i]=min(dp[j]+f[j],dp[i])
其中f数组存的是坐1~10站的费用,j去遍历i前面十个站,即不换乘就能坐到i的站。
现在就简单了啊,输入输出写好,dp双重循环就好了。

dp代码

就知道你爱看这个

#include <bits/stdc++.h>
using namespace std;
int n, f[103];
int main(){
	memset(f,0x3f3f3f3f,sizeof f);
	for(int i=1;i<=10;i++){
		scanf("%d",&f[i]);
	}
	scanf("%d",&n);
	for(int i=2;i<=n;i++){
		for(int j=1;j<i;j++){
			f[i]=min(f[i],f[j]+f[i-j]);
		}
	}
	printf("%d",f[n]);
}

dfs

搜索我就不细讲了,直接上代码吧:

#include<bits/stdc++.h>
using namespace std;
int n, a[13], ans=0x3f3f3f3f;
void dfs(int k, int mon){
	if(k>n)return;
	if(k==n){
		ans=min(ans,mon);
		return;
	}
	for(int i=1;i<=10;i++)dfs(k+i,mon+a[i]);
}
int main() {
	for(int i=1;i<=10;i++)scanf("%d",&a[i]);
	scanf("%d",&n);
	dfs(0,0);
	printf("%d",ans); 
}

这个题用搜索做很容易TLE,所以还是乖乖写动规叭~

废话

本蒟蒻没怎么写过题解,如有错误,还请各位大佬指正~

  • 28
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值