樹形dp-訪問美術館
阿新 • • 發佈:2018-11-06
主要問題: 樹如何編號(重點:如何體現父子關係)
樹的編號方式:
1)讀入給了編號並給予父子關係 (父子關係已給出) 處理:同存圖
2)將陣列轉化為一個樹 父子關係體現在其編號上(編號的關係->父子關係)典型:線段樹,堆(lson:2*x rson: 2*x+1)
void dfs(int x)
{
cin>>a[x].x>>a[x].w;
a[x].x*=2;
if(a[x].w==0)
{
dfs(x*2);dfs(x*2+1);
}
}
3)直接搞dfs序,一邊深搜一邊編號
void find() { cnt++;int x=cnt; int a,b;cin>>a>>b; if(b==0) { int l=cnt+1,r;find(); r=cnt+1;find(); v[x].push_back(l);v[x].push_back(r); } }
Then是完整程式碼
方法1:dfs序
由於輸入的訪問次序與dfs序相同,所以直接做一遍dfs找出lson,rson即可,無需額外儲存父子關係
#include <iostream> #include <cstdio> #include <vector> using namespace std; const int maxn=1005; vector<int> v[maxn]; int f[maxn][maxn]; int cnt=0; int n; void find() { cnt++;int x=cnt; int w,val;cin>>w>>val; w*=2; if(val==0) { int l=cnt+1,r;find(); r=cnt+1;find(); for(int tim=w;tim<=n;tim++) { for(int p=0;p<=tim-w;p++) { int temp=f[l][p]+f[r][tim-w-p]; f[x][tim]=max(f[x][tim],temp); } } } else { for(int tim=w;tim<=n;tim++) { f[cnt][tim]=min(val,(tim-w)/5); } } } int main() { cin>>n;n--; find(); cout<<f[1][n]<<endl; return 0; }
方法2:採用線段樹的儲存方法(lson=2*x,rson=2*x+1)
此方法可能存在空結點,沒有完全利用。
#include <iostream> #include <cstdio> #include <vector> using namespace std; const int maxn=1005; struct node { int x;int w; }a[maxn]; int f[maxn][maxn]; int cnt;node k; void dfs(int x) { cin>>a[x].x>>a[x].w; a[x].x*=2; if(a[x].w==0) { dfs(x*2);dfs(x*2+1); } } int find(int x,int cost) { if(cost==0||f[x][cost]) return f[x][cost]; if(a[x].w) return f[x][cost]=min(a[x].w,(cost-a[x].x)/5); for(int p=0;p<=cost-a[x].x;p++) { int temp=find(x*2,p)+find(x*2+1,cost-p-a[x].x); f[x][cost]=max(f[x][cost],temp); } return f[x][cost]; } int main() { int t;scanf("%d",&t);t-=1; dfs(1); cnt=0; cout<<find(1,t)<<endl; return 0; }