zoukankan      html  css  js  c++  java
  • 【Usaco2006Mar】Milk Team Select产奶比赛

    【思路分析】

    比赛的时候想到了用我确实也想到了树形DP,但是状态没有确定对,连样例都没有过
    PS:这是第二道发现还可以用状态作为答案最后输出的题目

    正解:树形DP(背包)

    按照读进来的数据,我们先建一棵树
    像这样(这里用vector存图)

    	for(int i=1;i<=n;++i){
    
    	int x=read(),y=read();
    	a[i]=x;	 v[y].push_back(i);//从父节点建一条边连向子节点
    }
    
    然后就是DP的过程
    (本人见到的树形DP题目比较少,但是做到过相关的题目似乎都是想这样子的)
    

    void dfs(int x){
    ***********************//这里写初始化,或者边界判断
    for(int i=0;i<v[x].size();i++){
    int nxt=v[x][i];
    dfs(nxt);//先处理它的子树
    ************************//这里写转移方程
    }
    ***************************//这里进行后续操作
    }

    确定了是树形dp之后,我们来想一下转移方程
    

    f[i][j][1]表示i节点分配j个亲缘关系取后最多的产奶量

    f[i][j][0]表示该节点分配j个亲缘关系不取后最多的产奶量

    然后像背包一样

    我们给第i个子树分配j个关系

    可以得出方程

    方程:

    (未加初始化与后续处理)
    f[x][j][0]=max(f[x][j][0],f[x][j-k][0]+max(f[nxt][k][0],f[nxt][k][1])),
    f[x][j][1]=max(f[x][j][1],f[x][j-k][1]+max(k==0?-0x3f3f3f3f:f[nxt][k-1][1],f[nxt][k][0]));
    

    AC代码大概是这样的:

    代码:

    #include<cstdio>
    #include<cmath>
    #include<cctype>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    using namespace std;
    inline int read()
    {
    	char chr=getchar();
    	int f=1,ans=0;
    	while(!isdigit(chr)) {if(chr=='-') f=-1;chr=getchar();}
    	while(isdigit(chr))  {ans=(ans<<1)+(ans<<3)+chr-'0';chr=getchar();}
    	return ans*f;
    }
    
    inline void kai()
    {
    	freopen("d.in","r",stdin);
    	freopen("d.out","w",stdout);
    }
    int n,m,a[505];
    vector<int> v[505];
    int f[505][505][2];
    void dfs(int x){
    	for(int i=1;i<=n;i++) f[x][i][0]=f[x][i][1]=-0x3f3f3f3f;//预处理
    	for(int i=0;i<v[x].size();i++){
    		int nxt=v[x][i];
    		dfs(nxt);//遍历子树
    		for(int j=n;j>=0;j--)
    			for(int k=0;k<=j;k++)
    			f[x][j][0]=max(f[x][j][0],f[x][j-k][0]+max(f[nxt][k][0],f[nxt][k][1])),
    			f[x][j][1]=max(f[x][j][1],f[x][j-k][1]+max(k==0?-0x3f3f3f3f:f[nxt][k-1][1],f[nxt][k][0]));//方程
    	}
    	for(int i=0;i<=n;i++) f[x][i][1]+=a[x];//后续处理
    }
    int ans=0,maxn=0;
    int main(){
    	n=read();
    	m=read();
    	for(int i=1;i<=n;++i){
    		int x=read(),y=read();
    		a[i]=x;	 v[y].push_back(i);//建树
    	}
    	dfs(0);//建一个“超级节点”(所有没有祖先的根节点都连到了0上)
    	int i;
    	for(i=n;i;i--) if(f[0][i][0]>=m) break;//用状态来做答案,找到第一个产奶量最多的亲缘关系(倒续找,所以最先找到的就是最大的)
    	cout<<i;
    	return 0;
    }
    
  • 相关阅读:
    VS缓冲区溢出,未对变量进行检查
    Mutex与Event控制互斥事件的使用详解
    error LNK2019: 无法解析的外部符号
    [转] 兼容IE和Firefox的设为首页和收藏的Javascript代码
    [转]超时时间以到,但尚未从池中获取连接
    Datalist的嵌套使用
    由服务器端向客户端输出脚本
    几个国外的XHTML模板站,DIV+CSS模板下载(转)
    gridview隐藏某一列
    [转]简单谈基于SQL SERVER 分页存储过程的演进
  • 原文地址:https://www.cnblogs.com/zhenglw/p/9507856.html
Copyright © 2011-2022 走看看