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

P5322 [BJOI2019]排兵布阵

因为看到这题目分类在分组背包下,所以一直在试图抽象出分组背包的模型来……最后很接近答案了,对于第(i)座城堡所有玩家的出兵数量视为一组物品……再想到分组背包的板子,应该每组只能挑一个物品。但是结合题目,挑的物品不一样收益也不一样,这个收益该怎么计算卡住了我……

看题解才恍然,直接对第(i)座城堡各个玩家的出兵数量排个序就完事了,这样挑了一个数量之后,收益就是小于这个数量的个数乘上(i),就这么简单。

const int maxn = 2e4 + 10;
int dp[maxn];
int cost[110][110], v[110];
bool cmp(int a, int b) {
    return a > b;
}
int main()
{
    //ios::sync_with_stdio(false);
    //while (scanf("%d%d",&n,&m)!=EOF){
    int s, n, m;
    cin >> s >> n >> m;
    for (int i = 1; i <= n; i++) v[i] = i;
    for (int i = 1; i <= s; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> cost[j][i];
            if (cost[j][i]) cost[j][i] = cost[j][i] * 2 + 1;
            else cost[j][i] = 1;
        }
    }
    for (int i = 1; i <= n; i++) sort(cost[i] + 1, cost[i] + 1 + s, cmp);
  //一开始写成了cost[i]+1+n……
    for (int i = 1; i <= n; i++) {
        //枚举组
        for (int j = m; j >= 0; j--) {
            //枚举容量
            for (int k = 1; k <= s; k++) {
                //枚举组内物品
                if (j >= cost[i][k]) dp[j] = max(dp[j], dp[j - cost[i][k]] + (s - k + 1) * v[i]);
            }
        }
    }
    cout << dp[m];
    return 0;
}
原文地址:https://www.cnblogs.com/streamazure/p/13688447.html