codeforces#1152D. Neko and Aki's Prank(dp)


題目鏈接:

https://codeforces.com/contest/1152/problem/D

題意:

給出一個$n$,然后在匹配樹上染色邊,每個結點的所有相鄰邊只能被染色一次。

問,這顆樹上最多染色多少邊。

匹配樹,就是深度為$2n$的樹,每個節點都是一個字符串,只包含$(,)$,以長度為$2n$的合法匹配字符串作為葉子。每個節點的父親是比自身長度小一的節點。

數據范圍:

$1 \le n \le 1000$

分析: 

在百度找了很久都沒找到滿意的題解,於是看了cf給的官方題解。雖然是全英文,但我居然看明白了!

實現起來不同,但是思路是一樣的。

貪心的方法是,先染色葉子和葉子節點的父親,並且去除它們,再染色葉子和葉子節點的父親。

定義不平衡度,$($的數量減$)$的數量。

長度為x,不平衡度為y的子樹染色方案數相同

例如這些節點$((()),()()(,(())($的子樹,染色方案數相同

選擇定義$dp[x][y]$,根節點長度為$x$,不平衡度為$y$,的子樹的染色方案數

轉移方程為

 

 

$ans=dp[0][0]$

ac代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e3+10;
const int maxm=1e7+10;
const int mod=1e9+7;
ll dp[2*maxn][2*maxn];
bool color[2*maxn][2*maxn];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=2*n-1;i>=0;i--)
    {
        for(int j=0;j<=2*n-i;j++)
        {
            int flag=0;
            if(j-1>=0)
            {
                dp[i][j]=(dp[i][j]+dp[i+1][j-1])%mod;
                if(color[i+1][j-1]==0)flag=1;
            }
            if(j+1<=2*n-i-1)
            {
                dp[i][j]=(dp[i][j]+dp[i+1][j+1])%mod;
                if(color[i+1][j+1]==0)flag=1;
            }
            if(flag)color[i][j]=1,dp[i][j]=(dp[i][j]+1)%mod;
        }
    }
    printf("%d\n",dp[0][0]);
    return 0;
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM