2012模擬国内予選E問題
単純な枝刈りで充分
軍事力順でソートして、残りを全て取って現状の最大値を超えられるか見る
以下、本番で提出したコード
#include <iostream> #include <algorithm> #include <string> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <cstdio> #include <cstdlib> #include <cmath> #include <complex> #include <cctype> #include <climits> #define FOR(i, c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i) #define each(i, c) FOR(i, c) typedef long long int lli; using namespace std; const int NODE = 40 + 1; lli p[NODE]; bool g[NODE][NODE]; int cand[NODE]; int vis[NODE]; int acc[NODE]; lli result; void put(int n, bool b, const int node) { for (int i = 0; i < node; ++i) { if (g[n][i]) { if (b) ++vis[i]; else --vis[i]; } } return ; } void rec(int i, lli sum, int node) { result = max(result, sum); if (sum + acc[i] < result) return ; for (int j = i + 1; j < node; ++j) { const int n = cand[j]; if (vis[n]) continue; put(n, true, node); rec(j, sum + p[n], node); put(n, false, node); } return ; } bool cmp(int a, int b) { return p[a] < p[b]; } int name(map<string, int> &m, string s) { if (m.count(s)) ; else { int tmp = m.size(); m[s] = tmp; } return m[s]; } int main(void) { int node; while (cin >> node && node) { fill(&g[0][0], &g[node - 1][node], false); fill(vis, vis + node, false); result = -1; map<string, int> M; for (int i = 0; i < node; ++i) { string a; int b, c; cin >> a >> b >> c; p[name(M, a)] = b; for (int j = 0; j < c; ++j) { string d; cin >> d; g[name(M, a)][name(M, d)] = true; } } for (int i = 0; i < node; ++i) { cand[i] = i; } sort(cand + 1, cand + node, cmp); reverse(cand + 1, cand + node); for (int i = 0; i < node; ++i) { acc[i] = 0; for (int j = i + 1; j < node; ++j) { acc[i] += p[cand[j]]; } } put(0, true, node); rec(0, p[0], node); cout << result << endl; } return 0; }