7.9 摆花 上学路线 严酷的训练(动态规划)

1.摆花

小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共 m 盆。通过调查顾客的喜好,小明列出了顾客最喜欢的 n 种花,从 1 到 n标号。为了在门口展出更多种花,规定第 i种花不能超过 ai​ 盆,摆花时同一种花放在一起,且不同种类的花需按标号的从小到大的顺序依次摆列。

试编程计算,一共有多少种不同的摆花方案。

输入格式

第一行包含两个正整数 n 和 m ,中间用一个空格隔开。

第二行有 nn 个整数,每两个整数之间用一个空格隔开,依次表示a1​ ,a2​ ,…, an​ 。

输出格式

一个整数,表示有多少种方案。注意:因为方案数可能很多,请输出方案数对 1000007 取模的结果。

InputcopyOutputcopy
2 4
3 2
2

Coding:每种花在每个数量状态下计算

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

int dp[1015][105];
int a[105];

int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	
	dp[0][0]=1;
	for(int i=1;i<=n;i++)
	for(int j=0;j<=m;j++)
	{
		for(int k=0;k<=min(a[i],j);k++)
		dp[i][j]=(dp[i][j]+dp[i-1][j-k])%1000007;
	}
	cout<<dp[n][m]<<endl;
	return 0;
}

2.上学路线 

 你所在城市的街道好像一个棋盘,有 a 条南北方向的街道和 b 条东西方向的街道。南北方向的 a 条街道从西到东依次编号为 l 到 a,而东西方向的 b 条街道从南到北依次编号为 l 到 b,南北方向的街道 i 和东西方向的街道 j的交点记为 (i,j)。

你住在 (1,1) 处,而学校在 (a,b) 处,你骑自行车去上学,自行车只能沿着街道走,而且为了缩短时间只允许沿着向东和北的方向行驶。

现在有 nn 个交叉路口在施工(X1​,Y1​)、(X2,Y2​)、………、(X_n,Y_n),这些路口是不能通车的。

问你上学一共有多少走法?

输入格式

第一行包含三个整数 a,b,n,分别表示街道的范围,有 n 个路口在维修。

接下来 n 行,每行两个整数 X_i,Y_i​,描述路口的位置。

输出格式

输出一个整数表示从 (1,1) 到 (a,b) 的行车路线总数。

样例解释

Sample 1

InputcopyOutputcopy
5 4 3
2 2
2 3
4 2
5

 很老的题了,很经典

Coding:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int dp[20][20];

int main()
{
    int a,b,n;
    cin>>a>>b>>n;
    for(int i=1;i<=b;i++)
    for(int j=1;j<=a;j++) dp[i][j]=-1;
    int x,y;
    for(int i=0;i<n;i++)
    {
    	cin>>x>>y;
    	dp[y][x]=0;
	}
	dp[0][1]=1;
	for(int i=1;i<=b;i++)
	for(int j=1;j<=a;j++)
	if(dp[i][j]!=0) 
	dp[i][j]=dp[i][j-1]+dp[i-1][j];
	cout<<dp[b][a];
	return 0;
}

3.严酷的训练

蒜头君在韭菜老师的带领下学习 OI,韭菜老师的训练方式很奇怪,他会一口气让蒜头君做很多道题,要求他在规定的时间完成。而韭菜老师为了让自己的威信提高,自己也会把这些题都做一遍。蒜头君和韭菜老师都有一个水平值,他们水平值的比值和做这些题所用时间的比值成反比。比如如果蒜头君的水平值是 1,韭菜老师的水平值是 2,那么蒜头君做同一道题的时间就是韭菜老师的 2 倍。

每个题目有他所属的知识点,这我们都知道,比如递归,动规,最短路,网络流……这里我们不考虑这些事情,我们只知道他们分别是知识点 1,知识点 2……

每一个同一知识点下的题目,对于蒜头君来讲,都是一样难的。做出每一道题,韭菜老师都有其独特的奖励值,而奖励值和题目的知识点没有必然联系。现在蒜头君同学请你帮忙计算,在韭菜老师规定的时间内,他所能得到最大奖励值是多少。

输入格式

第一行两个整数 K_1,K_2​,分别表示蒜头君和韭菜老师的水平值。

第二行两个整数 m,n,分别表示题目总数和知识点总数。

第三行 nn 个整数 t_i​,表示韭菜老师做每个知识点所花的时间。

接下来 mm 行,每行两个整数 x_i,y_i​,表示第 i 题的知识点编号和做出该题的奖励。

最后一行一个整数 T,表示规定的时间。

 

InputcopyOutputcopy
1 2
5 4
3 4 5 4
3 2
3 3
4 1
2 2
1 1
26
6

 和7.7的题很像,都是在一个固定的条件下

Coding:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

const int N=5000+5;
int a[N],dp[N];
int k1,k2,m,n,t;

struct Node
{
	int x,y;
}node[N];

int main()
{
	cin>>k1>>k2>>m>>n;
	for(int i=1;i<=n;i++)
	cin>>a[i],a[i]=(k2/k1)*a[i];
	
	for(int i=1;i<=m;i++)
	cin>>node[i].x>>node[i].y;
	cin>>t;
	
	for(int i=1;i<=m;i++)
	for(int j=t;j>=a[node[i].x];j--)
	dp[j]=max(dp[j],dp[j-a[node[i].x]]+node[i].y);
	cout<<dp[t]<<endl;
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值