poj-1463 Strategic game(树状DP入门)

https://vjudge.net/problem/POJ-1463

题意:一棵树,放哨兵站岗,如果有一个点放置了兵,那么与其相连的所有点都能被监视,求树的所有点都被监视且放置哨兵数目最少。

思路:dp[maxn][2]

dp[i][0]表示不选取该点,dp[i][1]表示选取该点。

若该点不选取,则其子节点必须都被选取。

若该点选取,则应选取min(dp[son][0],dp[son][1]);

类似的题目:https://blog.csdn.net/qq_38924883/article/details/82988994


#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#define maxn 1505
using namespace std;
int dp[maxn][2],degree[maxn],vis[maxn];
vector<int>v[maxn];
void dfs(int u)
{
    vis[u]=1;
    for(int i=0;i<v[u].size();i++)
    {
        if(vis[v[u][i]]) continue;
        dfs(v[u][i]);
        dp[u][0]+=dp[v[u][i]][1];
        dp[u][1]+=min(dp[v[u][i]][0],dp[v[u][i]][1]);
    }
}
int main()
{
    ///ios::sync_with_stdio(false);
    int n;
    while(cin>>n)
    {
        memset(degree,0,sizeof(degree));
        memset(vis,0,sizeof(vis));
        for(int i=0;i<maxn;i++)
            v[i].clear();
        int u,to,m;
        for(int i=0;i<n;i++)
        {
            dp[i][0]=0;dp[i][1]=1;
            scanf("%d:(%d)",&u,&m);
            for(int i=0;i<m;i++)
            {
                scanf("%d",&to);
                v[u].push_back(to);
                degree[to]++;
            }
        }
        int root;
        for(int i=0;i<n;i++)
        {
            if(degree[i]==0)
            {
                root=i;
                break;
            }
        }
        dfs(root);
        cout<<min(dp[root][0],dp[root][1])<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38924883/article/details/82989140