题解:P13521 [KOI 2025 #2] 包
本蒟蒻的第一篇题解。
这道题目,我们读懂了题目之后,肯定就会发现
:欸?这不就是一道贪心吗?
这道题的贪心策略其实非常明显:我们尽量在不超过当前包的限制的情况下尽量拿取重量小的物品,给小偷留下重量大的物品。
当你高高兴兴地写完了代码,提交之后发现:咦?怎么错了?
注意:这里其实有一个坑点,在物品数量小于 \(k\) 的情况下,小偷会把物品全部拿走。然而,如果我们背包容量足够大,我们拿走了大于 \(n\)-\(k\) 个物品,那么留下的物品就不足 \(k\) 个了。这样并不是最优情况,因为我们可以将多于 \(n\)-\(k\) 的物品给小偷偷走,这样就会使得小偷的物品总重量变大(反正你都要偷 \(k\) 个,还不如让你偷了呢,这样你的物品总重量就更重了。)
这里还有一个要注意的地方,我们直接枚举可能会超时,所以可以提前预处理一个前缀和来计算,这样的查询时间复杂度是 \(O(1)\) 的。
AC 代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,k,c,a[5005];
inline int faster_read()//快读
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+(ch-48);
ch=getchar();
}
return x*f;
}
inline void faster_write(int x)//快写
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9) faster_write(x/10);
putchar(x%10+48);
}
signed main()
{
n=faster_read();
k=faster_read();
c=faster_read();
for(int i=1;i<=n;i++) a[i]=faster_read();//读入数据
sort(a+1,a+1+n);//排序以保证最小的在前面
for(int i=1;i<=n;i++) a[i]+=a[i-1];//前缀和
int j=0;
int max_val=0;
for(int i=1;i<=c;i++)
{
while(j<=n&&a[j]<=i)
{
int cur_val;
if(j<=n-k) cur_val=a[j+k]-a[j];//如果没有超过n-k,将后k件物品给小偷
else cur_val=a[n]-a[j];
max_val=max(cur_val,max_val);//如果超过了n-k,那么将j+1~n的物品给小偷
j++;
}
faster_write(max_val);//输出答案
if(i!=c) putchar('\n');//末尾换行
}
return 0;
}

浙公网安备 33010602011771号