zoukankan      html  css  js  c++  java
  • [CF736C](Ostap and Tree)

    • 题意

    给定一个n个点的树,把其中一些点涂成黑色,使得对于每个点,它离与它最近的黑点的距离不超过K,求方案总数.

    • solution

    树形dp

    我们设(dp[i][r])

    状态:当前点为i,离i最近的黑点与i距离为r.

    dp[i][r]的意义: 在i的子树内 达成该状态的方案数

    更新方式当然是递归,让儿子更新父亲,同时把儿子的答案统计到父亲上,这样就把答案汇总到根上了.

    一开始我想的是r取值为0~k,结果是不行的,因为离i最近的黑点不仅可能在i的子树内,还可能在i的子树外

    但我们(在更新dp[i][r]时)只考虑了黑点在i的子树内的情况.

    所以r的取值应该在0~2*k间,这样 即使不合法也要记下来(重要!!) ,因为它子树外的黑点仍然可以使它变成合法的.

    然后我们考虑如何转移

    设v为u的儿子枚举v和u的dp值第二维

    对于dp[u][i]和dp[v][r],我们这样转移

    如果(i+(r+1)<=2 imes k+1)那么(tmp[min(i,r+1)]+=dp[u][i])(tmp为临时数组,转移后赋值到dp[u][i]上,代表u子树内的方案数统计)

    这个方程代表的意思是该方案可行时的转移,然后min(i,r+1)的意思是

    因为这个方案自身的问题已经解决,还(有余力)可以用来更新其他状态,简单的说就是min(i,r+1)代表的那个黑点还可以发挥作用

    如果(i+(r+1)>2 imes k+1)那么(tmp[max(i,r+1)]+=dp[u][i])

    这个方程代表的意思是该方案不可行时的转移,然后max(i,r+1)的意思是

    因为这个方案自身的问题还没解决,需要别的黑点来更新它,

    而因为要更新(使这个方案变得可行)就要照顾到所有点,而其中离黑点最远的点在哪里呢,就是在max(i,r+1)对应的黑点到u的链上,所以我们要把这条链更新,就应该记max(i,r+1)

    r+1是因为从u到v有1的距离

    初始化:dp[u][0]=1(u为黑点)dp[u][k+1]=1(u不为黑点,需要一个距离小于等于k的点来更新它)

    • code

    #include<bits/stdc++.h>
    #define N 205
    #define int long long//懒
    using namespace std;
    const int mod=1e9+7;
    vector<int> G[N];
    int dp[N][N];
    int plk[N];
    int n,k;
    void dfs(int x,int fa){
      dp[x][0]=dp[x][k+1]=1;
      for(int i=0;i<G[x].size();i++){
        int to=G[x][i];
        if(to==fa)continue;
        dfs(to,x);
        for(int i=0;i<=2*k+1;i++)plk[i]=0;
        for(int r=0;r<=2*k+1;r++)
        for(int p=0;p<=2*k;p++){
          if(r+p<=2*k)(plk[min(r,p+1)]+=1ll*dp[x][r]*dp[to][p])%=mod;
          else (plk[max(r,p+1)]+=1ll*dp[x][r]*dp[to][p])%=mod;
          }
        for(int r=0;r<=2*k+1;r++)dp[x][r]=plk[r];
        }
      }
    signed main(){
      scanf("%lld%lld",&n,&k);
      for(int i=1;i<n;i++){
        int a,b;
        scanf("%lld%lld",&a,&b);
        G[a].push_back(b);
        G[b].push_back(a);
        }
      dfs(1,0);
      int ans=0;
      for(int i=0;i<=k;i++)(ans+=dp[1][i])%=mod;
      cout<<ans;
    }
    
  • 相关阅读:
    [Swift]LeetCode823. 带因子的二叉树 | Binary Trees With Factors
    [Swift]LeetCode822. 翻转卡片游戏 | Card Flipping Game
    [Swift]LeetCode821. 字符的最短距离 | Shortest Distance to a Character
    [Swift]LeetCode818. 赛车 | Race Car
    [Swift]LeetCode817. 链表组件 | Linked List Components
    [Swift]LeetCode816. 模糊坐标 | Ambiguous Coordinates
    [Swift]LeetCode815. 公交路线 | Bus Routes
    [Swift]LeetCode814. 二叉树剪枝 | Binary Tree Pruning
    [Objective-C语言教程]指针(15)
    转 : net use的使用
  • 原文地址:https://www.cnblogs.com/stepsys/p/10488493.html
Copyright © 2011-2022 走看看