题目描述
小 C 正在玩一款排兵布阵的游戏。在游戏中有 nn 座城堡,每局对战由两名玩家来争夺这些城堡。每名玩家有 mm 名士兵,可以向第 ii 座城堡派遣 a_iai 名士兵去争夺这个城堡,使得总士兵数不超过 mm。
如果一名玩家向第 ii 座城堡派遣的士兵数严格大于对手派遣士兵数的两倍,那么这名玩家就占领了这座城堡,获得 ii 分。
现在小 C 即将和其他 ss 名玩家两两对战,这 ss 场对决的派遣士兵方案必须相同。小 C 通过某些途径得知了其他 ss 名玩家即将使用的策略,他想知道他应该使用什么策略来最大化自己的总分。
由于答案可能不唯一,你只需要输出小 C 总分的最大值。
输入格式
输入第一行包含三个正整数 s,n,ms,n,m,分别表示除了小 C 以外的玩家人数、城堡数和每名玩家拥有的士兵数。
接下来 ss 行,每行 nn 个非负整数,表示一名玩家的策略,其中第 ii 个数 a_iai 表示这名玩家向第 ii 座城堡派遣的士兵数。
输出格式
输出一行一个非负整数,表示小 C 获得的最大得分。
样例 1
Inputcopy | Outputcopy |
---|---|
1 3 10 2 2 6 | 3 |
小 C 的最佳策略为向第 11 座城堡和第 22 座城堡各派遣 55 名士兵。
样例 2
Inputcopy | Outputcopy |
---|---|
2 3 10 2 2 6 0 0 0 | 8 |
小 C 的最佳策略之一为向第 11 座城堡派遣 22 名士兵,向第 22 座城堡派遣 55 名士兵,向第 33 座城堡派遣 11 名士兵。
100% 的数据,保证
- 1001≤s≤100
- 1001≤n≤100
- 2\times 10^41≤m≤2×104
- 对于每名玩家,a_i \ge 0, \sum\limits_{i=1}^n a_i \le mai≥0,i=1∑nai≤m。
#include<cstring>
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<map>
#include<cmath>
//#include<unordered_map>
#include<string>
#include<stack>
#include<queue>
#include<set>
#include<stdlib.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 11;
ll s, n, m;
ll v[8] = { 1,5,10,25,50 };
//ll w[N];
ll bag[N];
ll peo[150][N];
//int six[N];
//struct node
//{
// int v,w;
//};
int main()
{
cin >> s >> n >> m;//s玩家人数,n城堡,m兵数
for (int i = 1;i <= s;i++)
{
for (int j = 1;j <= n;j++)
{
cin >> peo[j][i];//记录第i个玩家对第j个城堡的出兵数量
}
}
for (int i = 1;i <= n;i++)
{
sort(peo[i] + 1, peo[i] + 1 + s);//排序,将第i坐城堡的每个玩家对其出兵数量进行排序;;个人感觉其实不排序也是可以的
}
for (int i = 1;i <= n;i++)//开始遍历城堡
{
for (int j = m;j >= 1;j--)//
{//这里的j代表着小明对第i城堡出兵数量
for (int k = 1;k <= s;k++)//遍历每个玩家对第i个城堡出兵数
{
if (j > 2 * peo[i][k])bag[j] = max(bag[j], bag[j - 2 * peo[i][k] - 1] + k * i);//题目说当小明出兵数量大于其他玩家出兵数俩倍的时候获得i分,因此j > 2 * peo[i][k]才能更改bag里面的数值
/为什么还要再减去1,就类似于数学里面算日期之类的问题类似,然后为什么k*i:第i个玩家比的出兵数量必然是大于等于前面的数值(因为排序了)所以,当第k个玩家小明打得过,那么前面的玩家都是打的过的分数小明都能得到;
}
}
}
cout << bag[m];
return 0;
}