zoukankan      html  css  js  c++  java
  • [CQOI2017]小Q的棋盘

    题目大意:
      给你一个$n(nle100)$个点的树和一个数$m$,问从给定的点出发,任意游走$m(mle100)$次最多能走过几个点(重复经过点不计入答案)?

    思路:
      一眼看上去有种贪心的感觉。看Status里面一堆0ms的,AC率又那么高,果断写了一个$O(n)$贪心,每次贪心地走完最深的子树,结果交上去才30分,发现有时子树走一半就上去反而更优。
      考虑一个$O(n^3)$的DP。用$f[i][j]$表示$i$结点为根的子树走$j$次最后回到$i$最多能经过的点数,$g[i][j]$表示$i$结点为根的子树走$j$次步数用尽不回到$i$最多能经过的点数。转移方程显然:
      $f[x][i]=max{f[x][i-j-2]+f[y][j]}$
      $g[x][i]=max(max{f[x][i-j-1]+g[y][j]},max{g[x][i-j-2]+f[y][j]})$
      交一发80ms,看题解后发现那些0ms的人其实用的也是贪心,枚举结束位置的点,让剩下的步数尽量用完,即答案为$frac{min(max{dep[i]},m)+m}2+1$。时间复杂度$O(n)$。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<cstring>
     4 #include<algorithm>
     5 inline int getint() {
     6     register char ch;
     7     while(!isdigit(ch=getchar()));
     8     register int x=ch^'0';
     9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    10     return x;
    11 }
    12 const int N=100,M=200;
    13 int m,h[N],sz,f[N][N+1],g[N][N+1];
    14 struct Edge {
    15     int to,next;
    16 };
    17 Edge e[M];
    18 inline void add_edge(const int &u,const int &v) {
    19     e[sz]=(Edge){v,h[u]};h[u]=sz++;
    20     e[sz]=(Edge){u,h[v]};h[v]=sz++;
    21 }
    22 inline void dfs(const int &x,const int &par) {
    23     f[x][0]=g[x][0]=1;
    24     for(int i=h[x];~i;i=e[i].next) {
    25         const int &y=e[i].to;
    26         if(y==par) continue;
    27         dfs(y,x);
    28         for(register int i=m;i;i--) {
    29             for(register int j=0;j<i;j++) {
    30                 if(i-j-2>=0) {
    31                     f[x][i]=std::max(f[x][i],f[x][i-j-2]+f[y][j]);
    32                     g[x][i]=std::max(g[x][i],g[x][i-j-2]+f[y][j]);
    33                 }
    34                 g[x][i]=std::max(g[x][i],f[x][i-j-1]+g[y][j]);
    35             }
    36         }
    37     }
    38     for(register int i=1;i<=m;i++) {
    39         f[x][i]=std::max(f[x][i],f[x][i-1]);
    40         g[x][i]=std::max(g[x][i],g[x][i-1]);
    41     }
    42 }
    43 int main() {
    44     memset(h,-1,sizeof h);
    45     const int n=getint();m=getint();
    46     for(register int i=1;i<n;i++) {
    47         add_edge(getint(),getint());
    48     }
    49     dfs(0,0);
    50     printf("%d
    ",g[0][m]);
    51     return 0;
    52 }
  • 相关阅读:
    HDU 3152 Obstacle Course(BFS+优先队列 重载)
    芸芸毕业生
    shell学习三十四天----printf具体解释
    tomcat启动批处理——catalina.bat
    ZooKeeper启动过程2:FastLeaderElection
    R语言——数据分析的一把利剑
    Oracle blob字段的插入和更新
    [LeetCode] 698. Partition to K Equal Sum Subsets
    小知识!
    小知识!
  • 原文地址:https://www.cnblogs.com/skylee03/p/8782704.html
Copyright © 2011-2022 走看看