打地鼠游戏:
1.小C最近在研究一个打地鼠的游戏,游戏开始时,所有的地鼠都会出现在游戏的界面中,每个地鼠有两个属性:消失的时间t和分数s(即在第一秒到t秒之间打中地鼠就能获得s的分数,时间为t+1秒时,地鼠消失)。小C点击鼠标打一只地鼠的时间是1秒,打中之后地鼠会消失。给定n只地鼠的消失时间和分数,小C想知道他在这场游戏中最多能得到多少分数?
每组数据第一行,包含一个整数n,表示地鼠的数量\(1\le n\le 10^4\)。
接下来的每行,表示这只地鼠消失的时间\(1\le t_i\le 10^4\),每只地鼠可以获得分数\(2\le s_i\le 10^4\)
暴力+贪心
可以从大到小枚举分数,分数大的优先打,找空位的时间,如果没有空位时间了,打不了这只。复杂度o(n*T)
#include <bits/stdc++.h>
using namespace std;
struct node {
long long time;
long long score;
};
node ls[100005];
bool vis[100005];
bool cmp(node n1, node n2) { return n1.score > n2.score; }
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
long long n;
cin >> n;
long long time, score;
for (long long i = 0; i < n; i++) {
cin >> time >> score;
ls[i] = (node){ time, score };
}
sort(ls, ls + n, cmp);
long long sum = 0;
for (long long i = 0; i < n; i++) {
for (long long j = ls[i].time; j >= 1; j--) {
if (!vis[j]) {
vis[j] = true;
sum += ls[i].score;
break;
}
}
}
cout << sum << '\n';
return 0;
}
// by zsx
2.每组数据第一行,包含一个整数n,表示地鼠的数量\(1\le n\le 10^4\)。接下来的每行,表示这只地鼠消失的时间\(1\le t_i\le 10^9\),每只地鼠可以获得分数\(2\le s_i\le 10^9\)
分析:如果题目改成,有一些其他限制(比如瓷砖,比如飞盘队),前i只地鼠,打或者不打,获得的最大分数。很自然想到,前i个地鼠打j个的最大分数。
dfs(int i, int j, int sum){ dfs(i+1,j,sum); dfs(i+1,j+1,sum+a[i].v)};
那么限制条件是什么?
极小状态集:打了j个,j不仅表示的是最少用了j秒。
dp[i][j] 前i-1个地鼠,打了j-1个,相当于占用了j-1秒,已经求出来最大得分了。那么第i只地鼠,要不要打?因为前面已经占用了j-1秒,因此,第i只地鼠的消失时间必须大于j-1,即>=j,才能打。复杂度o(n^2)
#include <iostream>
#include <algorithm>
#include <cstring>
#define int long long
using namespace std;
int n, dp[3][10005], ans, T;
//每个时间有一张券,当前的地鼠消失的时间很晚为a[i].t,那么券就会给你很多,如果前面已经打了j只,则用了i张券,这样a[i].t
//- j >= 0
struct Node {
int t, s;
} a[10005];
bool cmp(Node x, Node y) { return x.t < y.t; }
signed main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i].t >> a[i].s;
sort(a + 1, a + n + 1, cmp);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
if (a[i].t - j >= 0)
dp[i % 2][j] = max(dp[(i - 1) % 2][j], dp[(i - 1) % 2][j - 1] + a[i].s);
else
dp[i % 2][j] = max(dp[i % 2][j], dp[(i - 1) % 2][j]);
if (i == n)
ans = max(ans, dp[n % 2][j]);
}
}
cout << ans << endl;
/*
o
o
o . o
*/
return 0;
}