题目描述
汤姆斯生活在一个等级为 0 的星球上。那里的环境极其恶劣,每天 12 小时的工作和成堆的垃圾让人忍无可忍。他向往着等级为 N 的星球上天堂般的生活。
有一些航班将人从低等级的星球送上高一级的星球,有时需要向驾驶员支付一定金额的费用,有时却又可以得到一定的金钱。
汤姆斯预先知道了从 0 等级星球去 N 等级星球所有的航线和需要支付(或者可以得到)的金钱,他想寻找一条价格最低(甚至获得金钱最多)的航线。
输入格式
第一行一个正整数 N(N < 100),接下来的数据可分为 N 个段落,每段的第一行一个整数 K_i(K_i < 100),表示等级为 i 的星球有 K_i 个。
接下来的 K_i 行中第 j 行依次表示与等级为 i,编号为 j 的星球相连的等级为 i - 1 的星球的编号和此航线需要的费用(正数表示支出,负数表示收益,费用的绝对值不超过 1000)。
每行以 0 结束,每行的航线数 < 100。
输出格式
输出所需(或所得)费用。正数表示支出,负数表示收益。
样例 #1
样例输入 #1
3
2
1 15 0
1 5 0
3
1 -5 2 10 0
1 3 0
2 40 0
2
1 1 2 5 3 -5 0
2 -19 3 -20 0
样例输出 #1
-1
提示
对于 100 % 的数据,1 < N < 100,1 < K_i < 100。
样例解释:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jEsrAJg0-1673855085919)(C:\Users\zc\Desktop\补题题解\img\652.png)]
显然,这是一道动态规划的问题,我们可以假设 f(i,j) 为到达等级为 i 的第 j 个星球所需要的最小费用。那么我们就可以很容易的写出它的转台转移方程:
f ( i , j ) = m i n ( f ( i , j ) , f ( i − 1 , t ) + a t ) 1 ≤ t ≤ k f(i,j)=min(f(i,j),f(i-1,t)+a_t)\quad 1\leq t \leq k f(i,j)=min(f(i,j),f(i−1,t)+at)1≤t≤k
其中,a_t表示从等级为 i-1 的第 t 个星球到等级为 i 的第 j 个星球所需要的代价, k 表示等级为 i-1 的星球最多有 k 个。
所以知道了状态转移方程后,我们就需要确定初始状态,初始状态就是到等级不为0的星球所需费用为无穷大(因为都还没到,所以就到不了,所以费用应该是无穷大)。我们只需要定义一个无穷大的值就行了。
当然,我不知道有没有和我一样的,这个输入方式是真的好绕,我看了好久才看懂这是怎么输入的QWQ。
话不多说,完整注释代码如下:
#include
using namespace std;
#define INF 0xfffffff
int N,K,f[105][105]; //f[i][j]表示到达等级为i的第j个星球所需的最小费用
int main(){
cin>>N;
int a,w,b;
for(int i=1;i<=N;i++){
for(int a=0;a<=N;a++){
f[i][a]=INF; //记得初始化
}
}
for(int i=1;i<=N;i++){ //好绕的输入方式QWQ
cin>>K; //代表等级为i的星球有K个
for(int a=1;a<=K;a++){
cin>>b; //表示i-1级星球中的第b个星球
while(b!=0){
cin>>w; //代表从i-1级星球中的第b个星球到达等级为i的第a个星球所需代价
f[i][a]=min(f[i-1][b]+w,f[i][a]); //取最小值
cin>>b;
}
}
}
int minn=INF;
for(int i=1;i<=K;i++){
minn=min(minn,f[N][i]); //在等级为N的星球中取最小值
}
cout<
题目描述
路人甲准备跑 n 圈来锻炼自己的身体,他准备分多次(>1)跑完,每次都跑正整数圈,然后休息下再继续跑。
为了有效地提高自己的体能,他决定每次跑的圈数都必须比上次跑的多。
可以假设他刚开始跑了 0 圈,那么请问他可以有多少种跑完这 n 圈的方案?
输入格式
一行一个整数,代表 n。
输出格式
一个整数表示跑完这 n 圈的方案数。
样例 #1
样例输入 #1
212
样例输出 #1
995645335
提示
数据规模与约定
对于 100% 的数据,保证 5< n< 500。
刚看到这道题目,我真的一点思路都没有,还是在看了题解后才恍然大悟:这竟然是个01背包问题!
然后我仔细一想,好像确实是01背包。
题目要求每次跑的圈数都比上次多,并且要刚好跑完 n 圈。那么我们其实可以把总圈数想象成容量为 n 的背包,把每次跑的圈数想象成重量为该圈数的物品,因为每次跑的圈数都要比上次多,所以一个物品只能取一次,那么这就是一道求01背包恰好装满背包的方案数的问题了。~~(真是太妙了啊)~
那么,我们知道了这么多,我们该怎么求呢?
首先,我们先回顾一下01背包问题的状态转移方程(先设 f(i,j) 为在前i件物品,容量为 j 的背包能得到的最大价值) :
f ( i , j ) = { f ( i − 1 , j ) w ( i ) > j m a x ( f (