[BJOI2019]排兵布阵

背包 ( exttt{dp})

把城堡看成为物品,派出的兵力为代价,获胜的场数乘上第几个城堡为价值。

(dp[i]) 表示已经派出 (i) 的兵力的最大价值。

那么我们考虑将每个人派出的兵力排序,枚举城堡 (i),由于已经排好序,能打败第 (k) 个敌人就能打败第 (k-1) 个,所以枚举敌人 (k),贪心地派出刚好比他的兵力两倍多 (1) 的兵力。

#include <bits/stdc++.h>
#define reg register
#define ll long long
#define ull unsigned long long
#define debug(typ...) fprintf(stderr,typ)
using namespace std;
int fastin() {
  reg int x=0,ch=getchar(),f=0;
  while(!isdigit(ch)) (ch=='-')&&(f=1),ch=getchar();
  while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
  return f?-x:x;
}
const int MAXN=110;
const int MAXM=2e4+10;
int s,n,m,dp[MAXM],a[MAXN][MAXN];
void work() {
  s=fastin(),n=fastin(),m=fastin();
  for(reg int i=1;i<=s;++i) for(reg int j=1;j<=n;++j) a[j][i]=fastin();
  for(reg int i=1;i<=n;++i) sort(a[i]+1,a[i]+s+1);
  for(reg int i=1;i<=n;++i) for(reg int j=m;j>=0;j--) for(reg int k=1;k<=s;++k)
    if(j>a[i][k]*2) dp[j]=max(dp[j],dp[j-a[i][k]*2-1]+i*k);
  int ans=0;
  for(reg int i=0;i<=m;++i) ans=max(ans,dp[i]);
  printf("%d
",ans);
}
signed main() {
  int _=1;
  // _=fastin();
  while(_--) {
    work();
  }
  return 0;
}
原文地址:https://www.cnblogs.com/Lonely-233/p/13768772.html