zoukankan      html  css  js  c++  java
  • 动态规划练习3

    题目描述:

          lw很喜欢玩一种战略游戏,在一个地图上,有n座城堡,每座城堡都有一定的宝物,在每次游戏中lw允许攻克m个城堡并获得里面的宝物。但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡。你能帮lw算出要获得尽量多的宝物应该攻克哪M个城堡吗?

    输入格式:

          第一行两个数,分别为n和m。接下来n行,每行两个数,第一个数a为攻克这个城堡前必须攻克的城堡,若a为0则该城堡可以直接攻克,第二个数b表示财宝数。

    输出格式:

          第一行一个数,即最大财宝数。

    样例输入:game.in

    3 2

    0 1

    0 2

    0 3

    样例输出:game.out

    5

    数据范围:

    对于30%的数据,n,m<=100。

    对于100%的数据,n,m<=200。

    题解:

    首先,限制条件是选择m个物品,而每个物品最多选一次,跟0-1背包的区别在于有依赖关系,那么这层依赖关系我们可以借助于一个树来解决。借助dfs,从根节点开始dfs,然后直到叶子节点,回朔的时候进行0-1背包dp。

    定义状态dp[i][j]表示在节点i,从以i为根节点的子树下选择j个城市的最大价值

    初始化:dp[i][j]=val[i](i节点的价值)(1 < = j < = m)

    转移方程 dp[father][j] = max (dp[father][j] dp[father][k]+dp[child][j-k]);由前面的dfs可见,我们是用子节点更新父节点,用j枚举父节点选择的城市数,k枚举留给其他子节点选择城市数,那么就可以转移了

    注意:此题出给很多初始节点,也就是有很多森林,我们要设置一个超级root连接子树的根节点即可。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    using namespace std;
    int f[1001][1001],n,m,a[1001];
    int gi()
    {
        int ans=0,f=1;
        char i=getchar();
        while(i<'0'||i>'9'){if(i=='-')f=-1;i=getchar();}
        while(i>='0'&&i<='9'){ans=ans*10+i-'0';i=getchar();}
        return ans*f;
    }
    struct node
    {
        int to,next;
    }edge[10001];
    int head[1001],size;
    void putin(int from,int to)
    {
        size++;
        edge[size].to=to;
        edge[size].next=head[from];
        head[from]=size;
    }
    void dfs(int r)
    {
        for(int i=head[r];i!=-1;i=edge[i].next)
        {
            dfs(edge[i].to);
            for(int j=m;j>=1;j--)
                for(int k=0;k<=j;k++)
                f[r][j]=max(f[r][j],f[r][k]+f[edge[i].to][j-k]);
        }
        for(int i=m+1;i>=1;i--)f[r][i]=f[r][i-1]+a[r];
    }
    int main()
    {
        freopen("game.in","r",stdin);
        freopen("game.out","w",stdout);
        int i,j;
        memset(head,-1,sizeof(head));
        n=gi();m=gi();
        for(i=1;i<=n;i++)
        {
            int c=gi(),b=gi();
            a[i]=b;
            putin(c,i);
        }
        dfs(0);
        printf("%d",f[0][m+1]);
        return 0;
    }
  • 相关阅读:
    【转】In ASP.NET using jQuery Uploadify upload attachment
    golang 初体验
    Node.js(express) + MongoDB(mongoose) 简单开发(二)
    Node.js(express) + MongoDB(mongoose) 简单开发(一)
    windows下修改mysql的root密码
    新网站添加百度官方认证
    手写单例模式
    浏览器内核
    IE内核浏览器
    没有猜中开头,更加没有预料结尾的我,正努力走在向程序媛发展的道路上……
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/7233857.html
Copyright © 2011-2022 走看看