zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    集训第六周 O题
    集训第六周 M题
    集训第六周 矩阵快速幂 K题
    集训第六周 数学概念与方法 计数 排列 L题
    集训第六周 数学概念与方法 J题 数论,质因数分解
    集训第六周 数学概念与方法 数论 线性方程 I题
    集训第六周 数学概念与方法 概率 N题
    HUAS Summer Contest#4 D题 DP
    集训第六周 数学概念与方法 数论 筛素数 H题
    C语言之六大排序算法
  • 原文地址:https://www.cnblogs.com/mrclr/p/9904520.html
Copyright © 2011-2022 走看看