[JSOI2016]最佳团体

嘟嘟嘟

01分数规划+树形背包。

然后就没了。

结果我调了半天,原因还是树形背包不熟练。

我是用dfs序求的,转化的时候,是dp[i][j]转化到dp[i + 1][j + 1]或dp[i +siz[pos[i]]][j],而不是像普通的dp从别的状态转化到dp[i][j],所以最后的答案应该考虑到dp[n + 1][m + 1],而不是只到n,而且初始化的时候也要到n + 1这一层。这也就是我为啥总WA第3个点。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cctype>
  8 #include<vector>
  9 #include<stack>
 10 #include<queue>
 11 using namespace std;
 12 #define enter puts("") 
 13 #define space putchar(' ')
 14 #define Mem(a, x) memset(a, x, sizeof(a))
 15 #define rg register
 16 typedef long long ll;
 17 typedef double db;
 18 const db INF = 1e12;
 19 const db eps = 1e-5;
 20 const int maxn = 2505;
 21 inline ll read()
 22 {
 23     ll ans = 0;
 24     char ch = getchar(), last = ' ';
 25     while(!isdigit(ch)) {last = ch; ch = getchar();}
 26     while(isdigit(ch)) {ans = (ans << 1) + (ans << 3) + ch - '0'; ch = getchar();}
 27     if(last == '-') ans = -ans;
 28     return ans;
 29 }
 30 inline void write(ll x)
 31 {
 32     if(x < 0) x = -x, putchar('-');
 33     if(x >= 10) write(x / 10);
 34     putchar(x % 10 + '0');
 35 }
 36 
 37 int k, n, s[maxn], p[maxn];
 38 struct Edge
 39 {
 40     int nxt, to;
 41 }e[maxn];
 42 int head[maxn], ecnt = -1;
 43 void addEdge(int x, int y)
 44 {
 45     e[++ecnt] = (Edge){head[x], y};
 46     head[x] = ecnt;
 47 }
 48 
 49 int dfsx[maxn], pos[maxn], cnt = 0;
 50 int siz[maxn];
 51 void dfs(int now)
 52 {
 53     dfsx[now] = ++cnt; pos[cnt] = now;
 54     siz[now] = 1;
 55     for(int i = head[now]; i != -1; i = e[i].nxt)
 56     {
 57         dfs(e[i].to);
 58         siz[now] += siz[e[i].to];
 59     }
 60 }
 61 db dp[maxn][maxn], w[maxn];
 62 db calc(int i, db x)
 63 {
 64     return (db)p[i] - (db)s[i] * x;
 65 }
 66 bool judge(db x)
 67 {
 68     for(int i = 1; i <= cnt; ++i) w[i] = calc(pos[i], x);
 69     for(int i = 1; i <= cnt + 1; ++i)
 70         for(int j = 0; j <= k + 1; ++j) dp[i][j] = -INF;
 71     dp[1][0] = 0;
 72     for(int i = 1; i <= cnt; ++i)
 73         for(int j = 0; j <= min(i, k + 1); ++j) if(dp[i][j] > -INF)
 74         {
 75             dp[i + 1][j + 1] = max(dp[i + 1][j + 1], dp[i][j] + w[i]);
 76             dp[i + siz[pos[i]]][j] = max(dp[i + siz[pos[i]]][j], dp[i][j]);
 77         }
 78     db ans = -INF;
 79     for(int i = 1; i <= cnt + 1; ++i) ans = max(ans, dp[i][k + 1]);
 80     return ans > -eps;
 81 }
 82 
 83 int main()
 84 {
 85     Mem(head, -1);
 86     k = read(); n = read();
 87     for(int i = 1; i <= n; ++i)
 88     {
 89         s[i] = read(); p[i] = read();
 90         int x = read();
 91         addEdge(x, i);
 92     }
 93     dfs(0);
 94     db L = 0, R = 1e4;
 95     while(R - L > eps)
 96     {
 97         db mid = (L + R) / 2;
 98         if(judge(mid)) L = mid;
 99         else R = mid;
100     }
101     printf("%.3lf
", L);
102     return 0;
103 }
View Code
原文地址:https://www.cnblogs.com/mrclr/p/9904520.html