Gym - 101116K ——Mixing Bowls(树形dp)

原题:https://odzkskevi.qnssl.com/efe310c5868f7c1881a7cec2c6b3e9cc?v=1487513501


You are following a recipe to create your lunch.The recipe is a mixture made by combining ingredients togetherin a bowl. Each ingredient will be either:Another mixture which you must make rst in a separate bowl;or A basic ingredient you already have in your kitchen, which canbe added directly. To make a mixture, you need to have all itsingredients ready, take an empty bowl and mix the ingredients init. It is not possible to make mixtures by adding ingredients to analready-existing mixture in a bowl.For example, if you want to make CAKE (a mixture) out of CAKEMIX(a mixture) and lies (a basic ingredient), then you must rstmake CAKEMIX in its own bowl, then add the CAKEMIX and lies toa second bowl to make the CAKE.Once you have used a mixture as an ingredient and emptied thebowl it was prepared in, you can re-use that bowl for anothermixture. So the number of bowls you need to prepare the recipewill depend on the order in which you decide to make mixtures.Determine the minimum number of bowls you will need.


其实想通的话就是一个简单的dfs。

首先可以通过复合物之间的关系建树。当你合成某一种复合物时,如果你需要使用x个碗,那么合成完以后,就会空出来x-1个碗,那么我当然希望,剩下需要的混合物的合成能利用这x-1个碗。所以我会选择先合成需要碗数量多的混合物,再用空出得碗去合成需要碗数量少得混合物。

对于每一个混合物,dfs出其原材料中每一种混合物需要的碗的数量,按其数量从大到小排序,第i个合成得混合物需要dp[i]个碗去合成这个混合物,还需要i-1个碗去装已经完成得混合物。所以就是i-1+dp[i]的最大值

另外如果原材料有y种混合物,那么你至少需要的碗得数量是y-1。


#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
using namespace std;
const int MAXN=2010;
struct node{
    int cnt;
    int num;
    int m;
    string name;
    string part[15];
};
node a[MAXN];
int cmp(int a,int b){
    return a>b;
}
map <string,int> mp;
void dfs(int x){
    if(a[x].cnt==0)
        return;
    int temp[15];
    int tot=0;
    for(int i=0;i<a[x].m;i++){
        if(isupper(a[x].part[i][0])){
            //cout<<"[[["<<a[x].part[i]<<" "<<mp[a[x].part[i]]<<endl;
            dfs(mp[a[x].part[i]]);
            temp[tot++]=a[mp[a[x].part[i]]].num;
        }
    }
    sort(temp,temp+tot,cmp);
    a[x].num=a[x].cnt+1;
    for(int i=0;i<tot;i++){
        a[x].num=max(a[x].num,temp[i]+i);
    }
    //cout<<a[x].name<<" "<<a[x].cnt<<" "<<a[x].num<<endl;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        cin>>a[i].name;
        mp.insert(make_pair(a[i].name,i));
        cin>>a[i].m;
        a[i].cnt=0;
        for(int j=0;j<a[i].m;j++){
            cin>>a[i].part[j];
            if(isupper(a[i].part[j][0]))
                a[i].cnt++;
        }
        if(a[i].cnt==0)
            a[i].num=1;
    }
    dfs(0);
    printf("%d\n",a[0].num);
    //system("pause");
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值