题目描述
我们把USACO竞赛的试题分为若干类,每类都有2道题目。同一类题目分值相同,耗时也相同。你的任务是编写一个程序决定选择那些题目,使得考生在给定的时间内能得到尽可能多的分数。
输入
输出
最大可能得到的分数
#include <bits/stdc++.h>
#pragma GCC optimize ("O2")
using namespace std;
int a[1009],v,n,b[1009],ans=INT_MIN;
void dfs(int dep,int r,int s)
{
if(dep>n)
{
ans=max(ans,s);
return ;
}
dfs(dep+1,r,s);
if(r>=a[dep])
dfs(dep+1,r-a[dep],s+b[dep]);
}
int main()
{
cin>>v>>n;
for(int i=1;i<=n;i++) cin>>a[i]>>b[i];
dfs(1,v,0);
cout<<ans<<endl;
return 0;
}
//有设么也问题
该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
在您提供的代码中,存在分数膨胀的问题,即同样的问题可能会被多次计算,从而导致得分偏高。这是因为在搜索过程中,每个问题只被考虑了一次,而实际上同一个问题可能会被选择多次,从而使得分数膨胀。
为了解决这个问题,可以采用记忆化搜索(Memoization)的方法,即在搜索过程中记录已经计算过的状态,避免重复计算。具体来说,可以使用一个二维数组 f[i][j]
表示在前 i
类问题中,用时不超过 j
分钟所能得到的最大分数。在搜索过程中,如果当前状态已经计算过,则直接返回已有的结果,否则进行搜索,并记录结果。
下面是使用记忆化搜索的 C++ 代码示例:
#include <bits/stdc++.h>
#pragma GCC optimize ("O2")
using namespace std;
int a[15], b[15];
int f[15][10001];
int dfs(int dep, int r) {
if (dep == 0 || r <= 0) {
return 0;
}
if (f[dep][r] != -1) {
return f[dep][r];
}
int ans = dfs(dep - 1, r);
if (r >= a[dep]) {
ans = max(ans, dfs(dep, r - a[dep]) + b[dep]);
}
f[dep][r] = ans;
return ans;
}
int main() {
int v, n;
cin >> v >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i] >> b[i];
}
memset(f, -1, sizeof(f));
cout << dfs(n, v) << endl;
return 0;
}
在上面的代码中,使用 f[i][j]
记录状态,初始化为 -1,表示尚未计算过。在搜索时,如果状态 f[i][j]
已经计算过,则直接返回结果,否则继续搜索,并记录结果。通过采用记忆化搜索的方法,可以避免分数膨胀的问题,得到正确的结果。
如果以上回答对您有所帮助,点击一下采纳该答案~谢谢