[lnsyoj3174/luoguP4823/TJOI2013]拯救小矮人
题意
给定序列 和常数 ,若序列中存在值 满足 ,则可将 删除,求从 中删除的数的数量最大为多少。
sol
由于 越小的数越靠后越难被删除,同时, 越大的数越可以帮助其他数字被删除,因此我们希望先被删除的数的 ,和 都更小,因此我们按照 来进行排序,然后进行一次 DP,计算前 个值中,被删掉 个值剩下的所有值的 为多少。此时,若该值 DP 值非负,说明这是一个合法状态,因此倒序枚举,若 DP 值非负,则直接输出即可。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 2005;
PII a[N];
int n, h;
int f[N][N];
bool cmp(PII a, PII b){
if (a.x + a.y != b.x + b.y) return a.x + a.y < b.x + b.y;
return a.x < b.x;
}
int main(){
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) scanf("%d%d", &a[i].x, &a[i].y);
scanf("%d", &h);
sort(a + 1, a + n + 1, cmp);
memset(f, -0x3f, sizeof f);
for (int i = 0; i <= n; i ++ ) {
f[i][0] = 0;
for (int j = 1; j <= n; j ++ )
f[i][0] += a[j].x;
}
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ ) {
f[i][j] = f[i - 1][j];
if (f[i - 1][j - 1] + a[i].y >= h) f[i][j] = max(f[i][j], f[i - 1][j - 1] - a[i].x);
}
// for (int i = 0; i <= n; i ++ ) printf("%d\n", f[n][i]);
for (int i = n; i >= 0; i -- )
if (f[n][i] >= 0) {
printf("%d\n", i);
return 0;
}
}
分类:
题解 / 2024训练
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现