Problem D. Soldiers
General Alice and General Bob are playing a war game. There are N soldiers in the game. Each soldier has two stats: attack and defense.
Before the game starts, General Alice and General Bob will take turns selecting soldiers, with General Alice going first. In each turn, a player can select one soldier, as long as that soldier either has an attack stat greater than each of the attack stats of all soldiers selected so far, or has a defense stat greater than each of the defense stats of all soldiers selected so far. To be precise: let Ai and Di be the attack and defense values for the i-th soldiers, for i from 1 to N, and let S be the set of soldiers that have been selected so far. Then a player can select soldier x if and only if at least one of the following is true:
- Ax > As for all s in S
- Dx > Ds for all s in S
General Alice wants to select more soldiers than General Bob, and General Bob wants to avoid that. If both players play optimally to accomplish their goals, can General Alice succeed?
Input
The first line of each case contains a positive integer N, the number of soldiers. N more lines follow; the i-th of these line contains two integers Ai and Di, indicating the attack and defense stats of the i-th soldier.
Output
For each test case, output one line containing Case #x: y
, where x
is the test case number (starting from 1) and y
is YES
or NO
, indicating whether General Alice can guarantee that she selects more soldiers than General Bob, even if General Bob plays optimally to prevent this.
Limits
1 ≤ T ≤ 10;
1 ≤ Ak, Dk ≤ 10000.
Small dataset
1 ≤ N ≤ 200.
Large dataset
1 ≤ N ≤ 4000.
Sample
Solution
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <list>
#include <iterator>
#include <unordered_set>
#include <unordered_map>
using namespace std;
typedef long long ll;
bool get_res(const vector<pair<int, int> >& soldiers, vector<bool> deleted, int N)
{
int MAXA, MAXD;
int n = N;
while (n > 0)
{
MAXA = MAXD = 0;
for (int i = 0; i < N; i++)
{
if (!deleted[i])
{
MAXA = max(soldiers[i].first, MAXA);
MAXD = max(soldiers[i].second, MAXD);
}
}
for (int i = 0; i < N; i++)
{
if (!deleted[i])
{
if (soldiers[i].first == MAXA)
{
if (soldiers[i].second == MAXD)
{
return true;
}
else
{
n--;
deleted[i] = true;
}
}
else if (soldiers[i].second == MAXD)
{
n--;
deleted[i] = true;
}
}
}
}
return false;
}
int main(int argc, char* argv[])
{
#ifndef TEST
if (argc != 2)
{
cout << "Invalid input" << endl;
return 1;
}
string input = argv[1];
string output = input.substr(0, input.length() - 2) + "out";
freopen(input.c_str(), "r", stdin);
freopen(output.c_str(), "w", stdout);
#endif
const int MAXN = 4000;
vector<pair<int, int> > soldiers(4000);
vector<bool> deleted(4000);
int T, N;
int A, D;
cin >> T;
for (int i = 1; i <= T; i++)
{
cin >> N;
for (int j = 0; j < N; j++)
{
cin >> A >> D;
soldiers[j] = make_pair(A, D);
deleted[j] = false;
}
bool flag = get_res(soldiers, deleted, N);
cout << "Case #" << i << ": " << (flag ? "YES" : "NO") << endl;
}
fclose(stdin);
fclose(stdout);
return 0;
}
Note
The solution to problem D is actually deceptively simple. Let's say whoever picks last wins.
If there are no soldiers, then Alice loses, because she has no moves. Otherwise, let the highest attack of the soldiers be maxA and the highest defense be maxD. We have two cases:
1. If there is a soldier with (Ai, Di) = (maxA, maxD), then Alice picks this soldier and wins immediately.
2. Otherwise, the players will never pick any soldier with attack maxA or defense maxD. The reason for this is that, if one player picks a soldier with attack maxA, the other immediately picks any soldier with defense maxD and wins. Therefore, as no soldiers with attack maxA or defense maxD will ever be picked, we can simply delete these soldiers and start again.
The straightforward O(n^2) implementation is good enough!
Reference
https://code.google.com/codejam/contest/6274486/dashboard#s=p3
http://codeforces.com/blog/entry/47181