ASDFZ 3633 -- 排兵布阵

Description

小 X 是生活在 9102 年的一位高二的 OIer,也是本套模拟题的主角。
这是一件往事了……
小 X 正在玩一款排兵布阵的游戏,这时候小 R 突然来找小 X 出去陪她玩。
于是小 X 把这个游戏丢给了你,希望你能帮他找到最优的策略,防止自己的不知道多少连胜断掉。
在游戏中有 n 座城堡,每局对战由两名玩家来争夺这些城堡。每名玩家有 m 名士兵,可以向第 i 座城堡派遣 ai名士兵去争夺这个城堡,使得总士兵数不超过 m。
如果一名玩家向第 i 座城堡派遣的士兵数严格大于对手派遣士兵数的两倍,那么这名玩家就占领了这座城堡,获得 i 分。
现在你即将和其他 s 名玩家两两对战,这 s 场对决的派遣士兵方案必须相同。小 X 通过某些途径得知了其他 s 名玩家即将使用的策略并告诉了你,你应该使用某种策略来最大化自己的总分。
由于方案可能不唯一,你只需要输出你能获得的总分的最大值。

Input

从标准输入读入数据。
输入第一行包含三个正整数 s,n,m,分别表示除了小 X 以外的玩家人数、城堡数和每名玩家拥有的士兵数。
接下来 s 行,每行 n 个非负整数,表示一名玩家的策略,其中第 i 个数 ai表示这名玩家向第 i 座城堡派遣的士兵数。

Output

输出到标准输出。
输出一行一个非负整数,表示你能获得的最大得分。

Sample Input

#1
1 3 10
2 2 6

#2
2 3 10
2 2 6
0 0 0

Sample Output

#1
3

#2
8

Sample Explanation

#1
一种最佳策略为向第 1 座城堡和第 2 座城堡各派遣 5 名士兵。

#2
一种最佳策略为向第 1 座城堡派遣 2 名士兵,向第 2 座城堡派遣 5 名士兵,向第 3 座城堡派遣 1 名士兵。

Hint

对于 10% 的数据,保证 s=1,n≤3,m≤10。
对于 20% 的数据,保证 s=1,n≤10,m≤100。
对于 40% 的数据,保证 n≤10,m≤100。
对于另外 20% 的数据,保证 s=1。
对于 100 的数据,保证
  • 1≤s≤100
  • 1≤n≤100
    - 1≤m≤2×10^4
  • 对于每名玩家,ai≥0,

请注意时间复杂度的常数因子对程序实际运行效率的影响。

Source

2019NOIP前训练

思路

fij表示选到前 i 座城堡已经用了j个士兵所能获得总分的最大值。倘若直接枚举每座城堡派几个士兵效率是 O(nm^2),但是我们发现只有多获胜一个人才能使总分增多,所以我们可以考虑枚举每座城堡赢几个人,效率变成O(nms)

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N=110,M=20010;

int a[N][N];
int s,n,m,f[M];

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]);
			a[j][i]=a[j][i]*2+1;
		}
	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-1; j>=0; j--)
			for(int k=1; k<=s; k++) {
				if(a[i][k]+j>m)
					break;
				f[a[i][k]+j]=max(f[a[i][k]+j],f[j]+k*i);
			}
	int ans=0;
	for(int i=1; i<=m; i++)
		ans=max(ans,f[i]);
	printf("%d\n",ans);
	return 0;
}
 

猜你喜欢

转载自www.cnblogs.com/mysh/p/11456531.html