week11-复习(floyd,01背包求方案数,01背包可行性判断,动态规划)

1.汤姆斯的天堂梦

题目描述

汤姆斯生活在一个等级为 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(i1,t)+at)1tk
其中,a_t表示从等级为 i-1 的第 t 个星球到等级为 i 的第 j 个星球所需要的代价, k 表示等级为 i-1 的星球最多有 k 个。

所以知道了状态转移方程后,我们就需要确定初始状态,初始状态就是到等级不为0的星球所需费用为无穷大(因为都还没到,所以就到不了,所以费用应该是无穷大)。我们只需要定义一个无穷大的值就行了。

当然,我不知道有没有和我一样的,这个输入方式是真的好绕,我看了好久才看懂这是怎么输入的QWQ。

话不多说,完整注释代码如下:

#include<bits/stdc++.h>
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<<minn;
	return 0;
}

2.跑步

题目描述

路人甲准备跑 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 (

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值