Luogu – P5322 – [BJOI2019]排兵布阵

题意

一个游戏,有 $n$ 座城堡,每局对战有两名玩家,每名玩家有 $m$ 个士兵,每人可以向第 $i$ 个城堡派遣 $a_i$ 名士兵,士兵总数满足:$a_1+a_2+\cdots+a_n\leq m$.

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

现给定 $s$ 名玩家及其各自的派兵策略,你需要选定一个固定的派兵策略,最大化你在 $s$ 场游戏中的总得分。

$1\leq s\leq 100, 1\leq n\leq 100, 1\leq m\leq 20000$.

分析

考虑DP。

设 $f_{i,j}$ 表示:对于前 $i$ 个城堡共派出 $j$ 个士兵;设 $a_{i,j}$ 表示:在城堡 $i$,玩家 $j$ 的出兵数量。

对每个城堡,把各个玩家在该城堡的出兵数量,按升序排序。

这样一来,若你在城堡 $i$ 的出兵数量大于 $2\times a_{i,j}$,则你可以在城堡 $i$ 获得 $i\times j$ 的得分。

于是对每个赢得城堡 $i$,枚举要战胜前 $k$ 个玩家,分别转移即可:

$$
f[i][j]=\max_{k=1}^s
\left\{
\begin{array}{lr}
0, &j-a_{i,k}\times 2 – 1 < 0\\
f[i][j-a_{i, k}\times2-1]+k\cdot i, &j-a_{i,k}\times2-1\geq 0
\end{array}
\right.
$$

属于分组背包模型。

代码

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 108, MAXM = 20008, MAXS = 108;
int s, n, m;
int dp[MAXM], a[MAXN][MAXS];//a[i][j]表示第i个城堡,第j个玩家
int main() {
	scanf("%d%d%d", &s, &n, &m);
	for(int i = 1; i <= s; i++)
		for(int j = 1; j <= n; j++)
			scanf("%d", &a[j][i]);
	for(int i = 1; i <= n; i++)
		sort(a[i] + 1, a[i] + s + 1);
	for(int k = 1; k <= n; k++) {
		for(int i = m; i > 0; i--) {
			for(int j = 1; j <= s; j++) {
				if(i >= a[k][j] * 2 + 1) {
					dp[i] = max(dp[i], dp[i - a[k][j] * 2 - 1] + k * j);
				}
			}
		}
	}
	cout << dp[m] << endl;
	return 0;
}

 

暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇