嘘~ 正在从服务器偷取页面 . . .

洛谷P5322 [BJOI2019] 排兵布阵 题解


洛谷P5322 [BJOI2019] 排兵布阵 题解

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

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

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

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

\(dp[i][j]\) 表示第 \(i\) 个城堡放 \(j\) 个士兵可以获得的最大分数

显然我们会选择恰好为某名玩家放的兵数 \(x\)\(2x+1\) ,不然多的都是浪费

因此这就是个类似背包的问题

没什么难度,直接看代码就能明白了吧(逃

时间复杂度 \(O(nms)\)

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define S (int)(105)
#define N (int)(115)
#define M (int)(2e4+15)
int s,n,m;
int val[N][M],dp[M],b[N][S],mx[N];
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> s >> n >> m;
    for(int i=1; i<=s; i++)
        for(int j=1; j<=n; j++)
            cin >> b[j][i];
    for(int i=1; i<=n; i++)
        sort(b[i]+1,b[i]+1+s);
    for(int i=1; i<=n; i++)
        for(int j=m; j>=1; j--)
            for(int k=1; k<=s; k++)
                if(j>2*b[i][k]) dp[j]=max(dp[j],dp[j-2*b[i][k]-1]+k*i);
    cout << dp[m] << endl;
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录