日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

NKOJ 1791 Party at Hali-Bula(树状DP)

發布時間:2025/6/15 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NKOJ 1791 Party at Hali-Bula(树状DP) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目大意是某些人將去參加一次party 但是他們和他們不能和他們的上司一起參加,問滿足此條件的情況下能去的最多人數

首先由給出的條件建好樹,我是用鄰接矩陣來存的,主要是為了方便,實際上效率還是比較低的。

需要保存兩個狀態 一是某節點不用(即此人不去的情況)時該節點和該節點子樹的最大值dp[i][0];

?? ? ? ? ? ? ? ? ? ? ? 二是是用該節點時,該節點及其子樹的最大值dp[i][1];

?

對于dp[i][1] 狀態轉移方程比較明顯 dp[i][1]=1+∑(dp[j][0])j是i的“孩子”;因為 i 去,則他的孩子就不能去了,所以此種情況下,能去的最大人數就是在他所有孩子不去的情況下的最大人數加他自己了。

?

dp[i][0]:由于i不去,i的孩子j也可去可不去 此時狀態轉移方程為: dp[i][0]=∑(max(dp[i][0],dp[i][1]))

?

還需判斷去的人數最多的情況,這些人是不是固定的。

?

對于葉子節點 pan[j][0]=1;pan[j][1]=1;表示人數是確定的。

?

對于任意節點i dp[i][1] 固定即pan[i][1]=1當且僅當 i 的所有孩子 j pan[j][0]=1;

?

dp[i][0] :

對于任意一個孩子 j 如果有 dp[ij[0]>dp[j][1]&&pan[j][0]==0或者 dp[j][0]<dp[j][1]&&pan[j][1]==0 或者dp[j][0]==dp[j][1]

?? ? ? ? ? ? ? ? pan[i][0]=0;

?

即,構成dp[i][0]的數據中,如果有一個是不確定的,那么dp[i][0]就是不確定的

?

我用的是記憶化搜索來實現DP的

代碼:

?

#include <iostream>

#include <cstring>

#include <cstdlib>

#include <stdio.h>

#include <map>

#include <algorithm>

using namespace std;

?

int n;

bool rela[210][210];

bool pan[210][2];

int dp[210][2];

?

int main()

{

?? ?while (cin>>n&&n)

?? ?{

?? ? ? ?memset(rela,0,sizeof(rela));

?? ? ? ?memset(pan,1,sizeof(pan));

?

?? ? for(int i=0;i<=n;++i){

?

?? ? ? ? dp[i][0]=dp[i][1]=-1;

?? ? ? ? }

?

?? ? ? ?map<string,int> myMap;

?? ? ? ?int i(1);

?? ? ? ?string a,b;

?? ? ? ?cin>>a;

?? ? ? ?myMap[a]=i;

?? ? ? ?int j(1);

?? ? ? ?while (j<n)

?? ? ? ?{

?? ? ? ? ? ?cin>>a;

?? ? ? ? ? ?cin>>b;

?? ? ? ? ? ?if (!myMap.count(a)) myMap[a]=++i;

?? ? ? ? ? ?if (!myMap.count(b)) myMap[b]=++i;

?

?? ? ? ? ? ?rela[myMap[b]][myMap[a]]=1;

?

?? ? ? ? ? ?++j;

?? ? ? ?}

/*

?? ? ? ?j=1;

?? ? ? ?while(j<=n){

?

?? ? ? ? ? ?int k(1);

?? ? ? ? ? ?while(k<=n){

?? ? ? ? ? ? ? ?cout<<rela[j][k]<<" ";

?? ? ? ? ? ? ? ?++k;

?? ? ? ? ? ? ? ?}

?? ? ? ? ? ?cout<<endl;

?? ? ? ? ? ?++j;

?? ? ? ? ? ?}

*/

?? ? ? ?void dfs(int n);

?? ? ? ?j=1;

?? ? ? ?while (j<=n)

?? ? ? ?{

?? ? ? ? ? ?dfs(j);

?? ? ? ? ? ?++j;

?? ? ? ?}

?

?? ? ? ?bool mul(0);

?? ? ? ?int maxOut=max(dp[1][1],dp[1][0]);

?? ? ? ?if(dp[1][1]>dp[1][0]&&!pan[1][1]) mul=1;

?? ? ? ?if(dp[1][1]<dp[1][0]&&!pan[1][0]) mul=1;

?? ? ? ?if(dp[1][1]==dp[1][0]) mul=1;

?

?

?? ? ? ?cout<<maxOut<<" ";

?? ? ? ?if (mul) cout<<"No"<<endl;

?? ? ? ?else cout<<"Yes"<<endl;

?? ?}

?

?? ?return 0;

}

?

void dfs(int num)

{

?

?

?? ?int j(1);

?? ?int tempA(0);

?? ?bool mulA(0);

?? ?int tempB(0);

?? ?bool mulB(0);

?? ?bool isLeaf(1);

?? ?while (j<=n)

?? ?{

?? ? ? ?if (rela[num][j])

?? ? ? ?{

?? ? ? ? ? ?isLeaf=0;

?

?? ? ? ? ? ?if (dp[j][0]==-1)

?? ? ? ? ? ? ? ?dfs(j);

?

?? ? ? ? ? ?if (!pan[j][0]) mulB=1;

?

?? ? ? ? ? ?tempA+=max(dp[j][1],dp[j][0]);

?? ? ? ? ? ?if ((dp[j][1]>dp[j][0]&&!pan[j][1])||(dp[j][1]<dp[j][0]&&!pan[j][0])||(dp[j][1]==dp[j][0]))

?? ? ? ? ? ? ? mulA=1;

?? ? ? ? ? ?tempB+=dp[j][0];

?

?? ? ? ?}

?

?? ? ? ?++j;

?? ?}

?? ?if (isLeaf)

?? ?{

?? ? ? ?dp[num][0]=0;

?? ? ? ?dp[num][1]=1;

?? ? ? ?return;

?? ?}

?

?? ?dp[num][0]=tempA;

?? ?dp[num][1]=tempB+1;

?

?

?? ?if (mulA) pan[num][0]=0;

?? ?if (mulB) pan[num][1]=0;

?? ?return;

}

總結

以上是生活随笔為你收集整理的NKOJ 1791 Party at Hali-Bula(树状DP)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。