洛谷P5322 [BJOI2019]排兵布阵【分组背包】

题目描述

小 C 正在玩一款排兵布阵的游戏。在游戏中有 n 座城堡,每局对战由两名玩家来争夺这些城堡。每名玩家有 m 名士兵,可以向第 i 座城堡派遣 a_i名士兵去争夺这个城堡,使得总士兵数不超过 m。

如果一名玩家向第 i 座城堡派遣的士兵数严格大于对手派遣士兵数的两倍,那么这名玩家就占领了这座城堡,获得 i 分。

现在小 C 即将和其他 s 名玩家两两对战,这 s 场对决的派遣士兵方案必须相同。小 C 通过某些途径得知了其他 s 名玩家即将使用的策略,他想知道他应该使用什么策略来最大化自己的总分。

由于答案可能不唯一,你只需要输出小 C 总分的最大值。

对于 100% 的数据:1≤s≤100,1≤n≤100,1≤m≤20000,对于每名玩家 ai≥0, ∑ i = 1 n a i ≤ m \sum\limits_{i=1}^n a_i \le m i=1naim

题目分析

数据范围看起来很大但其实就是分组背包裸题,复杂度为 O ( n m s ) O(nms) O(nms)但常熟很小所以能过
预处理出a[i][k]表示对第i座城堡第k小的出兵数
将每个城堡看成一个组,每个组共s个物品,体积和价值分别为 a [ i ] [ k ] ∗ 2 + 1 a[i][k]*2+1 a[i][k]2+1 k ∗ i k*i ki

const int maxN=210;
const int maxM=40010;
int s,n,m;
int a[maxN][maxN];
int dp[maxM];

int main()
{
    s=read(); n=read(); m=read();
    for(int i=1;i<=s;++i)
    for(int j=1;j<=n;++j)
    a[j][i]=read();
    
    for(int i=1;i<=n;++i)
    sort(a[i]+1,a[i]+1+s);
    
    for(int i=1;i<=n;++i)
    for(int j=m;j>=0;--j)
    for(int k=1;k<=s;++k)
    {
    	if(j<a[i][k]*2+1) break;
		dp[j]=max(dp[j],dp[j-a[i][k]*2-1]+k*i);
	}
    
    int ans=0;
    for(int i=1;i<=m;++i)
    ans=max(ans,dp[i]);
    printf("%d",dp[m]);
	return 0;
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值