AmazingCounters.com

[BZOJ]4813: [Cqoi2017]小Q的棋盘

Time Limit: 10 Sec  Memory Limit: 512 MB

Description

  小Q正在设计一种棋类游戏。在小Q设计的游戏中,棋子可以放在棋盘上的格点中。某些格点之间有连线,棋子只能在有连线的格点之间移动。整个棋盘上共有V个格点,编号为0,1,2…,V-1,它们是连通的,也就是说棋子从任意格点出发,总能到达所有的格点。小Q在设计棋盘时,还保证棋子从一个格点移动到另外任一格点的路径是唯一的。
  小Q现在想知道,当棋子从格点0出发,移动N步最多能经过多少格点。格点可以重复经过多次,但不重复计数。

Input

  第一行包含2个正整数V,N,其中V表示格点总数,N表示移动步数。
  接下来V-1行,每行两个数Ai,Bi,表示编号为Ai,Bi的两个格点之间有连线。
  V,N≤ 100, 0 ≤Ai,Bi<V 

Output

  输出一行一个整数,表示最多经过的格点数量。

Sample Input

  5 2
  1 0
  2 1
  3 2
  4 3

Sample Output

  3
  从格点 0 出发移动 2 步。经过 0, 1, 2 这 3 个格点。

Solution

  树形DP,f[i][j][0/1]表示走到点i,再往子树内走至多j步,回/不回到这个点最多遍历多少个点,随便转移下呗,复杂度$O(n^3)$。

Code

#include<cstdio>
#include<algorithm>
using namespace std;
inline int read()
{
    int x;char c;
    while((c=getchar())<'0'||c>'9');
    for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=x*10+c-'0';
    return x;
}
#define MN 100
struct edge{int nx,t;}e[MN*2+5];
int k,h[MN+5],en,f[MN+5][MN+5][2];
inline void ins(int x,int y)
{
    e[++en]=(edge){h[x],y};h[x]=en;
    e[++en]=(edge){h[y],x};h[y]=en;
}
void dp(int x,int fa)
{
    int i,j,l;
    for(i=0;i<=k;++i)f[x][i][0]=f[x][i][1]=1;
    for(i=h[x];i;i=e[i].nx)if(e[i].t!=fa)
    {
        dp(e[i].t,x);
        for(j=k;j;--j)for(l=0;l<j;++l)
        {
            if(j+1>l)f[x][j][0]=max(f[x][j][0],f[x][j-2-l][0]+f[e[i].t][l][0]);
                     f[x][j][1]=max(f[x][j][1],f[x][j-2-l][1]+f[e[i].t][l][0]);
            f[x][j][1]=max(f[x][j][1],f[x][j-1-l][0]+f[e[i].t][l][1]);
        }
    }
}
int main()
{
    int n,i;
    n=read();k=read();
    for(i=1;i<n;++i)ins(read(),read());
    dp(0,0);
    printf("%d",f[0][k][1]);
}
posted on 2017-04-21 10:31  ditoly  阅读(260)  评论(0编辑  收藏  举报