hdu4924 Football Manager

这题上来我是没有思路的。因为目标值关涉到的因素太多而直接枚举的复杂度又太高。

目标值由两部分合成,一部分是队员的CA和与PA和,另一部分是队员之间的relationship。

前者是简单的代数累加,而后者显然才是本题需要解决的问题。

由于relatioship由具体的出场方案所决定,因此不知道哪些队员上场就不可能知道它的值是多少,并且估算它有用的上下界也是困难的。

因此只能想到枚举,首先枚举哪些队员上场(这一步的复杂度就非常高,如果按题目给的数据范围对于强数据是根本不可能通过的)。

于是第二部分的值就确定了,现在只需要解决第一部分的求值。

这一部分不需要暴力枚举(如果仍然枚举仅在此处最坏情况下复杂度也会上万),因为既然是代数和的累加必然可以找到不同状态之间的联系。

对于某个特定的队员只会被任命在4个位置中的一个,现在方案只会是内部队员出场位置的调整。那么我们可以想到dp,通过枚举-更新的方法寻求最佳方案。

 

 

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <map>
  5 #include <string>
  6 #include <vector>
  7 #include <set>
  8 #include <cmath>
  9 #include <ctime>
 10 #pragma comment(linker, "/STACK:102400000,102400000")
 11 #define lson (u << 1)
 12 #define rson (u << 1 | 1)
 13 #define rep(i, a, b) for(i = a; i < b; i++)
 14 #define repi(i, a, b, c) for(i = a; i < b; i += c)
 15 #define cls(i, j) memset(i, j, sizeof i);
 16 using namespace std;
 17 typedef long long ll;
 18 const double eps = 1e-6;
 19 const double pi = acos(-1.0);
 20 const int maxn = 100 + 10;
 21 const int maxm = 1050;
 22 const int inf = 0x3f3f3f3f;
 23 const ll linf = 0x3fffffffffffffff;
 24 const ll mid = 1e9 + 7;
 25 
 26 struct P{
 27     int id, o[4];
 28     int c[4], p[4], cmax;
 29     bool operator < (const P &rhs) const{
 30         return cmax > rhs.cmax;
 31     }
 32 }a[maxn];
 33 
 34 int n, m;
 35 int idx[maxn];
 36 int g[maxn][maxn];
 37 
 38 int f(char ch){
 39     switch(ch){
 40         case 'G' : return 0;
 41         case 'D' : return 1;
 42         case 'M' : return 2;
 43         case 'S' : return 3;
 44     }
 45 }
 46 
 47 int select[20];
 48 int l[20];
 49 
 50 struct Point{
 51     int x, y;
 52     Point(int x = 0, int y = 0) : x(x), y(y) {}
 53     bool operator < (const Point &rhs){
 54         return x < rhs.x || x == rhs.x && y < rhs.y;
 55     }
 56     Point operator + (const Point &rhs){
 57         return Point(x + rhs.x, y + rhs.y);
 58     }
 59     bool operator == (const Point &rhs){
 60         return x == rhs.x && y == rhs.y;
 61     }
 62 }dp[15][15][15][15];//i, 0, 1, 2
 63 
 64 Point ANS, INF = Point{-inf, -inf};
 65 
 66 Point max(Point lhs, Point rhs) { return lhs < rhs ? rhs : lhs; }
 67 
 68 void update(int u, int kind, int n0, int n1, int n2){
 69     Point dest = dp[u][n0][n1][n2] + Point{a[select[u]].c[kind], a[select[u]].p[kind]};
 70     Point *src = &dp[u + 1][n0 + (0 == kind)][n1 + (1 == kind)][n2 + (2 == kind)];
 71     (*src) = max((*src), dest);
 72 }
 73 
 74 void cal(){
 75     int cnt[4];
 76     cls(cnt, 0);
 77     int i, j, k, u, v;
 78     rep(i, 0, 11) rep(j, 0, 4) if(a[select[i]].o[j]) ++cnt[j];
 79     rep(i, 0, 4) if(cnt[i] < l[i]) return;
 80     int ca = 0;
 81     rep(i, 0, 11) rep(j, i, 11){
 82         int x = a[select[i]].id, y = a[select[j]].id;
 83         ca += g[x][y];
 84         if(i != j) ca += g[y][x];
 85     }
 86     int high = ca;
 87     rep(i, 0, 11) high += a[select[i]].cmax;
 88     if(high < ANS.x) return;//curcial pruning
 89     rep(i, 0, 12) rep(j, 0, cnt[0] + 1)
 90     rep(k, 0, cnt[1] + 1) rep(u, 0, cnt[2] + 1) dp[i][j][k][u] = INF;
 91     dp[0][0][0][0] = Point{0, 0};
 92     rep(i, 0, 11) rep(j, 0, l[0] + 1) rep(k, 0, l[1] + 1) rep(u, 0, l[2] + 1){
 93         if(dp[i][j][k][u] == INF) continue;
 94         rep(v, 0, 4) if(a[select[i]].o[v]) update(i, v, j, k, u);
 95     }
 96     ANS = max(ANS, Point(ca, 0) + dp[11][l[0]][l[1]][l[2]]);
 97 }
 98 
 99 void fswap(int x, int y){
100     int i;
101     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]);
102     swap(l[x], l[y]);
103 }
104 
105 void dfs(int pos, int num){
106     //num::how many palyers has been chosen
107     if(num == 11){
108         cal();
109         return;
110     }
111     if(pos == n || n - pos + num < 11) return;
112     select[num] = pos;
113     dfs(pos + 1, num + 1);
114     dfs(pos + 1, num);
115 }
116 
117 void solve(){
118     ANS = INF;
119     dfs(0, 0);
120     if(ANS == INF) puts("Poor Manager!");
121     else printf("%d %d\n", ANS.x, ANS.y);
122 }
123 
124 int main(){
125     //freopen("in.txt", "r", stdin);
126     int T;
127     scanf("%d", &T);
128     char buf[10];
129     while(T--){
130         scanf("%d", &n);
131         int i, j, tem;
132         rep(i, 0, n) rep(j, 0, 4) a[i].o[j] = 0;
133         rep(i, 0, n){
134             a[i].cmax = -inf;
135             scanf("%d%d", &a[i].id, &tem);
136             rep(j, 0, tem){
137                 scanf("%s", buf);
138                 int tem1 = f(buf[0]);
139                 a[i].o[tem1] = 1;
140                 scanf("%d%d", &a[i].c[tem1], &a[i].p[tem1]);
141                 a[i].cmax = max(a[i].cmax, a[i].c[tem1]);
142             }
143         }
144         cls(g, 0);
145         sort(a, a + n);
146         scanf("%d", &m);
147         rep(i, 0, m){
148             int u, v, w;
149             scanf("%d%d%s%d", &u, &v, buf, &w);
150             g[u][v] = (buf[0] == 'D' ? -1 : 1) * w;
151         }
152         scanf("%d-%d-%d", &l[1], &l[2], &l[3]);
153         l[0] = 11 - l[1] - l[2] - l[3];
154         int maxp = 3, maxv = l[3];
155         rep(i, 0, 3) if(l[i] > maxv) maxv = l[i], maxp = i;
156         if(maxp != 3) fswap(3, maxp);
157         solve();
158     }
159     return 0;
160 }
View Code

 

posted @ 2015-10-26 21:24  astoninfer  阅读(151)  评论(0编辑  收藏  举报