1187. 【动态规划】竞赛总分

发布于:2025-04-19 ⋅ 阅读:(60) ⋅ 点赞:(0)

题目描述

学生在我们USACO的竞赛中的得分越多我们越高兴。我们试着设计我们的竞赛以便人们能尽可能的多得分。
现在要进行一次竞赛,总时间T固定,有若干类型可选择的题目,每种类型题目可选入的数量不限,每种类型题目有一个si(解答此题所得的分数)和ti(解答此题所需的时间),现要选择若干题目,使解这些题的总时间在T以内的前提下,所得的总分最大。  

输入

输入包括竞赛的时间,M(1 <= M <= 10000)和题目类型数目N(1 <= N <= 10000)。
后面的每一行将包括两个整数来描述一种"题型"。第一个整数说明解决这种题目能得的分数(1 <= points <= 10000),第二整数说明解决这种题目所需的时间(1 <= minutes <= 10000)。

输出

单独的一行,在给定固定时间里得到的最大的分数。

样例输入

300 4
100 60
250 120
120 100
35  20

样例输出

605

思路

动态规划可以分成四部分

        dp1: 状态定义

                dp[i] 表示时间为i的最大的分数

        dp2: 初始化数据

                数组全部初始化为0

        dp3: 求解算法(状态转移方程)

               

if (i + v1[j].second <= n) 枚举时间, 时间+当前题目的时间 <= 规定的时间(满足条件)
	dp[i + v1[j].second] = max(dp[i + v1[j].second], dp[i] + v1[j].first);

dp[i + v1[j].second] 选择之后的时间所达到的分数
= max(选择之后的时间原来所达到的分数, 没有选择的时候的分数 + 当前题目的分数)

很多dp都是这样子的模式

        dp4: 输出答案

                dp[n] 

Code

#include <bits/stdc++.h>
using namespace std;

int n, m;
typedef pair<int, int> Ipair;
vector<Ipair> v1;
void Print(vector<int> dp)
{
	for (auto& it : dp) cout << it << ' ';
	cout << endl;
}
int main() {
	cin >> n >> m;
	v1.resize(m + 1);
	for (int i = 1; i <= m; i++) cin >> v1[i].first >> v1[i].second;
	
	vector<int> dp(n + 1, 0); // dp数组, dp[i] 表示时间为i的最大分数
	
	// dp第二步: 求解
	for (int i = 0; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			if (i + v1[j].second <= n)
				dp[i + v1[j].second] = max(dp[i + v1[j].second], dp[i] + v1[j].first);
		}
		//Print(dp);
	}
	cout << dp[n];
    return 0;
}

网站公告

今日签到

点亮在社区的每一天
去签到