zoukankan      html  css  js  c++  java
  • 洛谷P3354 [IOI2005]Riv 河流——“承诺”DP

    题目:https://www.luogu.org/problemnew/show/P3354

    状态中要记录一个“承诺”,只需相同承诺之间相互转移即可;

    然后就是树形DP的套路了。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    int n,m,head[105],ct,siz[105],fa[105],len[105];
    ll ed[105],f[105][55][105][3];//点,伐木场个数,前伐木场,是否有伐木场 
    ll a[105],c[105][105];//c:从i到j代价 
    struct N{
        int to,next;
        ll w;
        N(int t=0,int n=0,ll w=0):to(t),next(n),w(w) {}
    }edge[100005];
    void init(int cr,int cnt,ll dis,int nw)
    {
        c[cr][cnt]=dis*a[cr];
        if(cnt)f[cr][0][cnt][0]=c[cr][cnt];
        if(!nw)
        {
            len[cr]=cnt;return;
        }
        init(cr,cnt+1,dis+ed[nw],fa[nw]);
    }
    void dfs(int x)
    {
        siz[x]=1;
        for(int j=1;j<=n;j++)f[x][j][0][1]=0;
        for(int k=1;k<=len[x];k++)f[x][1][k][1]=0;
        for(int i=head[x],v;i;i=edge[i].next)
        {
            dfs(v=edge[i].to);
            for(int j=min(m,siz[x]+siz[v]);j>=0;j--)
            {
                for(int k=0;k<=len[x];k++)
                {
                    f[x][j][k][0]+=min(f[v][0][k+1][0],f[v][0][k+1][1]);
                    f[x][j][k][1]+=min(f[v][0][1][0],f[v][0][1][1]);
                    for(int l=max(1,j-siz[x]);l<=j&&l<=siz[v];l++)
                    {
                        f[x][j][k][0]=min(f[x][j][k][0],f[x][j-l][k][0]+min(f[v][l][k+1][0],f[v][l][k+1][1]));
                        f[x][j][k][1]=min(f[x][j][k][1],f[x][j-l][k][1]+min(f[v][l][1][0],f[v][l][1][1]));
                    }
                }
            }
            siz[x]+=siz[v];
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1,x;i<=n;i++)
        {
            scanf("%lld%d%lld",&a[i],&x,&ed[i]);
            edge[++ct]=N(i,head[x],ed[i]);head[x]=ct;
            fa[i]=x;
        }
        memset(f,1,sizeof f);f[0][0][0][0]=0;//!
        for(int i=1;i<=n;i++)init(i,0,0,i);
        dfs(0);
        printf("%lld",f[0][m][0][0]);
        return 0;
    }
  • 相关阅读:
    汉语-词语:什么
    汉语-词语:甚么
    汉语-汉字:心
    汉语-词汇:头脑
    汉语-词语:冰冷
    汉语-词汇:冷静
    两个int类型的数据相加,有可能会出现超出int的表示范围。
    两个int类型的数据相加,有可能会出现超出int的表示范围。
    成员变量与局部变量的区别_
    函数额基本概述
  • 原文地址:https://www.cnblogs.com/Zinn/p/9139344.html
Copyright © 2011-2022 走看看