【HDU1561】 더 많을수록 좋다 | 트리 형 배낭, 트리 형 dp

주요 아이디어 :

ACboy는 전략 게임을 좋아합니다.지도에는 N 개의 성이 있고 각성에는 특정 보물이 있습니다. 각 게임에서 ACboy는 M 개의 성을 정복하고 내부의 보물을 얻을 수 있습니다. 그러나 지리적 인 이유로 일부 성을 직접 정복 할 수없는 경우가 있으므로이 성을 정복하려면 먼저 다른 특정 성을 정복해야합니다. ACboy가 가능한 한 많은 보물을 얻기 위해 정복해야하는 M 성을 파악하도록 도와 줄 수 있습니까?

질문 아이디어 :

이 유형의 트리 dp가 더 분명합니다.

dp [u] [k]는 종속성이 있기 때문에 노드 u에서 선택된 k 항목의 최대 값을 나타냅니다.

따라서 상태 전환에주의를 기울이고, 전환에 포함되지 않도록 불법 상태 dp [u] [0]에 특별한주의를 기울이십시오.

전체 사진이 숲이기 때문에 모든 나무를 달리고 배낭에 의지

전체 그림에서 숲에 대한 그룹화 배낭을 실행하십시오.

암호:

/*** keep hungry and calm CoolGuang!  ***/
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define d(x) printf("%lld\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17;
const ll maxn = 2e5+700;
const int mod= 1e9+7;
const int up = 1e9;
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
vector<int>v[maxn];
ll dp[2005][2005];
int num[maxn],in[maxn];
ll dpc[2005];
void dfs(int u){
    dp[u][1] = num[u];
    for(int e:v[u]){
        dfs(e);
        for(int k=m;k>=1;k--)
            for(int j=1;j<=k-1;j++)
                dp[u][k] = max(dp[u][k],dp[u][k-j]+dp[e][j]);
    }
}
int main(){
    while(~scanf("%lld%lld",&n,&m)&&n&&m){
        for(int i=1;i<=n;i++) in[i] = 0,v[i].clear();
        for(int i=1;i<=n;i++){
            int x;read(x);read(num[i]);
            if(x) v[x].push_back(i),in[i]++;
        }
        for(int i=1;i<=n;i++)
            for(int k=0;k<=m;k++)
                dp[i][k] = 0;
        for(int i=1;i<=n;i++)
            if(!in[i])
                dfs(i);
        for(int i=0;i<=m;i++) dpc[i] = 0;
        for(int i=1;i<=n;i++){
            if(!in[i]){
                for(int k=m;k>=0;k--){
                    for(int j=0;j<=k;j++){
                        dpc[k] = max(dpc[k],dpc[k-j] + dp[i][j]);
                    }
                }
            }
        }
        ll ans = 0;
        for(int i=0;i<=m;i++) ans = max(ans,dpc[i]);
        printf("%lld\n",ans);
    }
    return 0;
}

/***
4 3
0 0
1 0
2 0
3 1
****/

 

추천

출처blog.csdn.net/qq_43857314/article/details/111314289