原题链接:https://blog.csdn.net/weixin_43773540/article/details/105388870
时间限制:3s
描述:
有2N张牌,它们的点数分别为1到2N,Alice拿到了其中的N张,Bob拿了剩下的N张,Alice和Bob会进行N轮游戏,在每轮游戏中,Alice和Bob各出了一张牌,出了的牌不能收回,在前N/2轮中,每轮谁的牌点数大谁就赢;在后N/2轮中,每轮谁的牌点数小谁就赢。已知(这里原题应该是错别字)Bob每一轮会出什么牌,试求Alice最多能赢多少轮。
输入
第一行是一个整数N
接下来N行,每行一个整数,表示Bob这轮会出什么
2<=N<=50000,保证N是偶数
输出
输出Alice最多能赢几轮
样例输入
4
1
8
4
3
样例输出
2
思路
PS.做题的时候满脑子的【所列瓦多卡纳】(那可不一定)
1 先顺着题意建模
2 模拟游戏规则穷举Alice的出牌方案
PS. 这位置可能有人觉得链接里题解的排序对半分可以搞定,但我觉得数量一多,Alice如果使用田忌赛马的策略调整出牌顺序就真的【所列瓦多卡纳】了,反正是电脑穷举一下也不会很费时间,3s应该够用
3 选出最优方案
代码
排列组合的工具类就看这里吧,不知道比赛的时候能不能再添加个类
https://blog.csdn.net/snowdust/article/details/5216571
List<string> readLineString = new List<string>()
{
"4",
"1",
"8",
"4",
"3",
//"4",
//"1",
//"2",
//"7",
//"8",
};
int N = int.Parse(readLineString[0]);
readLineString.RemoveAt(0);
List<int> cardsOfAlice = new List<int>();
List<int> cardsOfBob1 = new List<int>();
List<int> cardsOfBob2 = new List<int>();
for (int i = 0; i < 2 * N; i++)
{
if (cardsOfBob1.Count < N / 2)
cardsOfBob1.Add(int.Parse(readLineString[i]));
else if (cardsOfBob2.Count < N / 2)
cardsOfBob2.Add(int.Parse(readLineString[i]));
if (i != 0 && !readLineString.Contains(i + ""))
cardsOfAlice.Add(i);
}
List<int[]> combinations = PermutationAndCombination<int>.GetPermutation(cardsOfAlice.ToArray());
int winMaxCount = 0;// Alice赢的次数
foreach (var combination in combinations)
{
int winCount = 0;// Alice赢的次数
for (int i = 0; i < N; i++)
if ((i < N / 2 && cardsOfBob1[i] < combination[i])// 比大
|| (i >= N / 2 && cardsOfBob2[i - N / 2] > combination[i]))// 比小
winCount++;
if (winCount > winMaxCount)
winMaxCount = winCount;
}
Console.WriteLine(winMaxCount);
Console.ReadKey();