Description
小 X 是生活在 9102 年的一位高二的 OIer,也是本套模拟题的主角。
这是一件往事了……
小 X 正在玩一款排兵布阵的游戏,这时候小 R 突然来找小 X 出去陪她玩。
于是小 X 把这个游戏丢给了你,希望你能帮他找到最优的策略,防止自己的不知道多少连胜断掉。
在游戏中有 n 座城堡,每局对战由两名玩家来争夺这些城堡。每名玩家有 m 名士兵,可以向第 i 座城堡派遣 ai名士兵去争夺这个城堡,使得总士兵数不超过 m。
如果一名玩家向第 i 座城堡派遣的士兵数严格大于对手派遣士兵数的两倍,那么这名玩家就占领了这座城堡,获得 i 分。
现在你即将和其他 s 名玩家两两对战,这 s 场对决的派遣士兵方案必须相同。小 X 通过某些途径得知了其他 s 名玩家即将使用的策略并告诉了你,你应该使用某种策略来最大化自己的总分。
由于方案可能不唯一,你只需要输出你能获得的总分的最大值。
这是一件往事了……
小 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 座城堡派遣的士兵数。
输入第一行包含三个正整数 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
1 3 10
2 2 6
#2
2 3 10
2 2 6
0 0 0
Sample Output
#1
3
#2
8
3
#2
8
Sample Explanation
#1
一种最佳策略为向第 1 座城堡和第 2 座城堡各派遣 5 名士兵。
#2
一种最佳策略为向第 1 座城堡派遣 2 名士兵,向第 2 座城堡派遣 5 名士兵,向第 3 座城堡派遣 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 的数据,保证
请注意时间复杂度的常数因子对程序实际运行效率的影响。
对于 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; }