zoukankan      html  css  js  c++  java
  • 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
    ", 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
  • 相关阅读:
    获取有关控件的坐标
    Android PopupWindow的使用和分析
    Android RecyclerView 使用完全解析 体验艺术般的控件
    TextView中显示价格并且中间直接有一个横线
    Android Studio
    移动开发】Android中三种超实用的滑屏方式汇总(ViewPager、ViewFlipper、ViewFlow)
    Android中visibility属性VISIBLE、INVISIBLE、GONE的区别
    理解Java的IO流 2015年8月6日 21:30:38
    算法导论学习随笔——第七章 快速排序
    oj 1031 random permutation
  • 原文地址:https://www.cnblogs.com/astoninfer/p/4912480.html
Copyright © 2011-2022 走看看