hdu4924 Football Manager
2015-10-26 21:24
232 查看
这题上来我是没有思路的。因为目标值关涉到的因素太多而直接枚举的复杂度又太高。
目标值由两部分合成,一部分是队员的CA和与PA和,另一部分是队员之间的relationship。
前者是简单的代数累加,而后者显然才是本题需要解决的问题。
由于relatioship由具体的出场方案所决定,因此不知道哪些队员上场就不可能知道它的值是多少,并且估算它有用的上下界也是困难的。
因此只能想到枚举,首先枚举哪些队员上场(这一步的复杂度就非常高,如果按题目给的数据范围对于强数据是根本不可能通过的)。
于是第二部分的值就确定了,现在只需要解决第一部分的求值。
这一部分不需要暴力枚举(如果仍然枚举仅在此处最坏情况下复杂度也会上万),因为既然是代数和的累加必然可以找到不同状态之间的联系。
对于某个特定的队员只会被任命在4个位置中的一个,现在方案只会是内部队员出场位置的调整。那么我们可以想到dp,通过枚举-更新的方法寻求最佳方案。
View Code
目标值由两部分合成,一部分是队员的CA和与PA和,另一部分是队员之间的relationship。
前者是简单的代数累加,而后者显然才是本题需要解决的问题。
由于relatioship由具体的出场方案所决定,因此不知道哪些队员上场就不可能知道它的值是多少,并且估算它有用的上下界也是困难的。
因此只能想到枚举,首先枚举哪些队员上场(这一步的复杂度就非常高,如果按题目给的数据范围对于强数据是根本不可能通过的)。
于是第二部分的值就确定了,现在只需要解决第一部分的求值。
这一部分不需要暴力枚举(如果仍然枚举仅在此处最坏情况下复杂度也会上万),因为既然是代数和的累加必然可以找到不同状态之间的联系。
对于某个特定的队员只会被任命在4个位置中的一个,现在方案只会是内部队员出场位置的调整。那么我们可以想到dp,通过枚举-更新的方法寻求最佳方案。
#include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <string> #include <vector> #include <set> #include <cmath> #include <ctime> #pragma comment(linker, "/STACK:102400000,102400000") #define lson (u << 1) #define rson (u << 1 | 1) #define rep(i, a, b) for(i = a; i < b; i++) #define repi(i, a, b, c) for(i = a; i < b; i += c) #define cls(i, j) memset(i, j, sizeof i); using namespace std; typedef long long ll; const double eps = 1e-6; const double pi = acos(-1.0); const int maxn = 100 + 10; const int maxm = 1050; const int inf = 0x3f3f3f3f; const ll linf = 0x3fffffffffffffff; const ll mid = 1e9 + 7; struct P{ int id, o[4]; int c[4], p[4], cmax; bool operator < (const P &rhs) const{ return cmax > rhs.cmax; } }a[maxn]; int n, m; int idx[maxn]; int g[maxn][maxn]; int f(char ch){ switch(ch){ case 'G' : return 0; case 'D' : return 1; case 'M' : return 2; case 'S' : return 3; } } int select[20]; int l[20]; struct Point{ int x, y; Point(int x = 0, int y = 0) : x(x), y(y) {} bool operator < (const Point &rhs){ return x < rhs.x || x == rhs.x && y < rhs.y; } Point operator + (const Point &rhs){ return Point(x + rhs.x, y + rhs.y); } bool operator == (const Point &rhs){ return x == rhs.x && y == rhs.y; } }dp[15][15][15][15];//i, 0, 1, 2 Point ANS, INF = Point{-inf, -inf}; Point max(Point lhs, Point rhs) { return lhs < rhs ? rhs : lhs; } void update(int u, int kind, int n0, int n1, int n2){ Point dest = dp[u][n0][n1][n2] + Point{a[select[u]].c[kind], a[select[u]].p[kind]}; Point *src = &dp[u + 1][n0 + (0 == kind)][n1 + (1 == kind)][n2 + (2 == kind)]; (*src) = max((*src), dest); } void cal(){ int cnt[4]; cls(cnt, 0); int i, j, k, u, v; rep(i, 0, 11) rep(j, 0, 4) if(a[select[i]].o[j]) ++cnt[j]; rep(i, 0, 4) if(cnt[i] < l[i]) return; int ca = 0; rep(i, 0, 11) rep(j, i, 11){ int x = a[select[i]].id, y = a[select[j]].id; ca += g[x][y]; if(i != j) ca += g[y][x]; } int high = ca; rep(i, 0, 11) high += a[select[i]].cmax; if(high < ANS.x) return;//curcial pruning rep(i, 0, 12) rep(j, 0, cnt[0] + 1) rep(k, 0, cnt[1] + 1) rep(u, 0, cnt[2] + 1) dp[i][j][k][u] = INF; dp[0][0][0][0] = Point{0, 0}; rep(i, 0, 11) rep(j, 0, l[0] + 1) rep(k, 0, l[1] + 1) rep(u, 0, l[2] + 1){ if(dp[i][j][k][u] == INF) continue; rep(v, 0, 4) if(a[select[i]].o[v]) update(i, v, j, k, u); } ANS = max(ANS, Point(ca, 0) + dp[11][l[0]][l[1]][l[2]]); } void fswap(int x, int y){ int i; rep(i, 0, n) swap(a[i].c[x], a[i].c[y]), swap(a[i].p[x], a[i].p[y]), swap(a[i].o[x], a[i].o[y]); swap(l[x], l[y]); } void dfs(int pos, int num){ //num::how many palyers has been chosen if(num == 11){ cal(); return; } if(pos == n || n - pos + num < 11) return; select[num] = pos; dfs(pos + 1, num + 1); dfs(pos + 1, num); } void solve(){ ANS = INF; dfs(0, 0); if(ANS == INF) puts("Poor Manager!"); else printf("%d %d\n", ANS.x, ANS.y); } int main(){ //freopen("in.txt", "r", stdin); int T; scanf("%d", &T); char buf[10]; while(T--){ scanf("%d", &n); int i, j, tem; rep(i, 0, n) rep(j, 0, 4) a[i].o[j] = 0; rep(i, 0, n){ a[i].cmax = -inf; scanf("%d%d", &a[i].id, &tem); rep(j, 0, tem){ scanf("%s", buf); int tem1 = f(buf[0]); a[i].o[tem1] = 1; scanf("%d%d", &a[i].c[tem1], &a[i].p[tem1]); a[i].cmax = max(a[i].cmax, a[i].c[tem1]); } } cls(g, 0); sort(a, a + n); scanf("%d", &m); rep(i, 0, m){ int u, v, w; scanf("%d%d%s%d", &u, &v, buf, &w); g[u][v] = (buf[0] == 'D' ? -1 : 1) * w; } scanf("%d-%d-%d", &l[1], &l[2], &l[3]); l[0] = 11 - l[1] - l[2] - l[3]; int maxp = 3, maxv = l[3]; rep(i, 0, 3) if(l[i] > maxv) maxv = l[i], maxp = i; if(maxp != 3) fswap(3, maxp); solve(); } return 0; }
View Code
相关文章推荐
- fputs和fgets fread和fwrite
- POJO属性对拷(支持嵌套和继承)
- 【随机算法】Miller-Rabin大素数检测算法(蒙特卡罗方法)
- 拿nodejs快速搭建简单Oauth认证和restful API server攻略
- light oj 1100 - Again Array Queries
- C语言使用正则表达式
- 中断的系统调用
- leetcode contains duplicate III
- [TwistedFate]OC面向对象
- 查看索引的使用情况(show status like 'Handler_read%')
- Oracle基本用法
- 01-MyEclipse新建JavaWeb项目并发布到Tomcart下
- 2015-10-26 那一点破事
- C# DataGridView内容合并相同的行
- Code:Blocks输入中文出现乱码
- 常用命令代码
- Codeforces Round #322 (Div. 2)
- leetcode之路046 Permutations
- pygame编写的坦克游戏(六)
- UITableView 编辑