zoukankan      html  css  js  c++  java
  • YBT 5.2 树形动态规划

    题解在代码中

    二叉苹果树[loj 10153]

    /*
    若要留q条边便是要留q+1个点
    所以记忆化搜索 
    dp[pos][ans]=max(dp[pos][ans],dp[l[pos]][k]+dp[r[pos]][ans-k-1]+a[pos])
    0<=k<=ans-1 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return ans*f;
    }
    int n,q; 
    int book[101][101],a[101],l[101],r[101];
    void dfs(int pos){
        for(int i=1;i<=n;i++)
        {
            if(book[pos][i]!=-1)
            {
                a[i]=book[pos][i];
                book[pos][i]=-1;book[i][pos]=-1;
                l[pos]=i;
                dfs(i);
                break;
            }
        }
        for(int i=1;i<=n;i++)
        {
            if(book[pos][i]!=-1)
            {    
                a[i]=book[pos][i];
                book[pos][i]=-1;book[i][pos]=-1;
                r[pos]=i;
                dfs(i);
                break;
            }
        }
        return;
    }
    int dp[101][101];
    int solve(int pos,int ans)
    {
        if(ans==0) return 0;
        if(dp[pos][ans]!=-1) return dp[pos][ans];
        if(r[pos]==0&&l[pos]==0) return a[pos];
        for(int j=0;j<=ans-1;j++) 
            dp[pos][ans]=max(dp[pos][ans],solve(l[pos],j)+solve(r[pos],ans-1-j)+a[pos]);
        return dp[pos][ans];
        
    }
    int main()
    {
        memset(dp,-1,sizeof(dp)); 
        memset(book,-1,sizeof(book));
        n=read(),q=read();
        for(int i=1;i<n;i++) 
        {
            int u=read(),v=read(),w=read();book[u][v]=w;book[v][u]=w;
        }
        dfs(1);
        cout<<solve(1,q+1);
    }
    View Code

    选课[loj 10154]

    /*
    建立一个虚根0使得将森林转化成为树
    dp[i][j]表示为以i为根的子树下最多选j门课的最大学分
    dfs后先进行背包处理
    这是先不考虑先修课
    再将有先修课 (pos!=0)时dp的容积为容积-1的最大值加上选修此门课的积分 
    dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[son][k])
    j (m~0)
        k(j~0) 
    */ 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return ans*f;
    }
    int n,m;
    struct node{
        int u,v,nex;
    }x[1001];
    int s[1001];
    int t,cnt;
    int dp[1001][1001],head[1001];
    void add(int u,int v)
    {
        x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
    }
    void dfs(int pos)
    {
        for(int p=head[pos];p!=-1;p=x[p].nex)
        {
            int xx=x[p].v;
            dfs(xx);
            for(int i=m;i>=0;i--)
                for(int j=i;j>=0;j--) dp[pos][i]=max(dp[pos][i],dp[pos][i-j]+dp[xx][j]);
        }
        if(pos!=0)
        {
            for(int i=m;i>=1;i--)  dp[pos][i]=dp[pos][i-1]+s[pos];
        }
            
    //    for(int i=m;i>=0;i--) cout<<"位置:"<<pos<<"  选课:"<<i<<"  dp:"<<dp[pos][i]<<endl;
    //    system("pause"); 
        return ;
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        n=read(),m=read();
        for(int i=1;i<=n;i++) 
        {
            t=read(),s[i]=read();
            add(t,i);
        }
        dfs(0);
        cout<<dp[0][m];
    }
    View Code

    数字转换[loj 10155]

    /*
    先预处理好因数和,再建一棵树 
    求树的最长链即可 
    */ 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #pragma GCC optimize(2)
    using namespace std;
    inline long long read()
    {
        long long f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return ans*f;
    }
    long long n,cnt;
    struct node{
        long long u,v,nex;
    }x[100001];
    long long head[100001];
    long long dp1[100001],dp2[100001];
    void add(long long u,long long v)
    {
        x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
    }
    long long sum[100001];
    long long maxn,book[100001];
    //dp1表示最长,dp2表次长 
    void dfs(long long pos)
    {
    //    cout<<pos<<endl;
        for(long long i=head[pos];i!=-1;i=x[i].nex)
        {
            long long p=x[i].v;
            if(book[p]==0)
            {
                book[p]=1;
                dfs(p);
                if(dp1[p]+1>dp1[pos]) dp2[pos]=dp1[pos],dp1[pos]=dp1[p]+1;
                else if(dp1[p]+1>dp2[pos]) dp2[pos]=dp1[p]+1;
                maxn=max(maxn,dp1[pos]+dp2[pos]); 
            }
        }
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        n=read();
        for(int i=1;i<=n/2;i++)
        {
            for(int j=i*2;j<=n;j+=i) 
            {
                sum[j]+=i;
            }
        }
        for(int i=2;i<=n;i++)
            if(sum[i]<i) add(sum[i],i),add(i,sum[i]);
        book[1]=1;
        dfs(1);
        cout<<maxn;
    }
    View Code

    战略游戏[loj 10156]

    /*
    0为不选,1为选
    pos的子孙为x
    dp[pos][0]=sum(dp[x][1]) 
    dp[pos][1]=sum(min(dp[x][0],dp[x][1]));
    */ 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return ans*f;
    }
    struct node{
        int u,v,nex;
    }x[100001];
    int head[1501],n,cnt,dp[1501][3],book[1501];
    void add(int u,int v)
    {
        x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
    }
    void dfs(int pos)
    {
    //    cout<<pos<<endl;
        dp[pos][1]=1;
        for(int i=head[pos];i!=-1;i=x[i].nex)
        {
            int p=x[i].v;
            if(book[p]==0)
            {
                book[p]=1;
                dfs(p);
                dp[pos][0]+=dp[p][1];
                dp[pos][1]+=min(dp[p][0],dp[p][1]);
    //            cout<<pos<<" "<<dp[pos][0]<<" "<<dp[pos][1]<<" "<<endl;
            }
        }
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        n=read();
        for(int i=1;i<=n;i++)
        {
            int t=read(),k=read();
            for(int j=1;j<=k;j++)
            {
                int p=read();
                add(t,p),add(p,t);
            }
        }
        book[0]=1;
        dfs(0);
        cout<<min(dp[0][0],dp[0][1]);
    }
    View Code

    皇宫看守[loj 10157]

    /*
    dp[pos][0]为pos自己安放 
    dp[pos][1]为pos被自己的父亲看到
    dp[pos][2]为pos被自己的子孙看到
    
    dp[pos][0]+=min(dp[x][0],dp[x][1],dp[x][2]) 
    dp[pos][1]+=min(dp[x][0],dp[x][2])
    dp[pos][2]+=min(dp[x][0],dp[x][2])
    dp[pos][2]+=k,dp[pos][0]+=s[pos]
    k=min(k,dp[pos][0]-min(dp[pos][0],dp[pos][2]));
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return ans*f;
    }
    int dp[1501][3];
    struct node{
        int u,v,nex;
    }x[2250001];
    int s[1501];
    int a[1501],cnt,n;
    int head[1501];
    void add(int u,int v)
    {
        x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
    }
    int dfs(int pos,int fath)
    {
        int k=99999999;
        for(int i=head[pos];i!=-1;i=x[i].nex)
        {
            int p=x[i].v;
            if(p==fath) continue;
            dfs(p,pos);
            dp[pos][0]+=min(min(dp[p][0],dp[p][1]),dp[p][2]);
            dp[pos][1]+=min(dp[p][0],dp[p][2]);
            dp[pos][2]+=min(dp[p][0],dp[p][2]);
            k=min(k,dp[p][0]-min(dp[p][0],dp[p][2]));
        }
        dp[pos][0]+=s[pos];
        dp[pos][2]+=k;
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        n=read();
        for(int i=1;i<=n;i++)
        {
            int xx=read();
            s[xx]=read();
            int m=read();
            for(int j=1;j<=m;j++)
            {
                int p=read();
    //            cout<<xx<<" "<<p<<endl;
                add(xx,p);
                add(p,xx);
            }
        }
        dfs(1,0);
        cout<<min(dp[1][0],dp[1][2]);
    }
    View Code

    加分二叉树[loj 10158]

    /*
    中序遍历
    左子树——根——右子树
    每次枚举根
    进行记忆化dfs
    将last存放最优根 
    */ 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return ans*f;
    }
    int dp[31][31],s[31],n,last[31][31];
    int dfs(int l,int r)
    {
    //    cout<<l<<" "<<r<<endl;
        if(l==r) return s[l];
        if(l>r) return 1;
        if(dp[l][r]!=-1) return dp[l][r];
        for(int i=l;i<=r;i++)
        {
            int p=dfs(l,i-1)*dfs(i+1,r)+s[i];
            if(p>dp[l][r])
            {
                dp[l][r]=p;
                last[l][r]=i;
            }
        }
        return dp[l][r];
    }
    void sc(int l,int r)
    {
        
        if(l>r) return;
        if(l==r)
        {
            cout<<l<<" ";
            return;
        }
        cout<<last[l][r]<<" ";
        sc(l,last[l][r]-1);
        sc(last[l][r]+1,r);
        return;
    }
    int main()
    {
        memset(dp,-1,sizeof(dp));
        n=read();
        for(int i=1;i<=n;i++) s[i]=read();
        cout<<dfs(1,n)<<endl;
    //    cout<<
        sc(1,n);
    }
    View Code

    旅游规划[loj 10159]

    /*
    此题是找最长链上的所有店
    dp1求子树上最长路径
    dp2求子树上次长路径
    
    两者相加便可以求出最长路径的长度
    
    dp3记录除子树外的最长路径
    
     
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return ans*f;
    }
    struct node{
        int u,v,nex;
    }x[400001];
    int n,cnt,head[200001]; 
    int book[200001],dp3[200001],maxn,dp1[200001],dp2[200001];
    void add(int u,int v)
    {
        x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
    }
    void dfs(int pos)
    {
    //    cout<<pos<<endl;
        for(int i=head[pos];i!=-1;i=x[i].nex)
        {
            int p=x[i].v;
    //        cout<<p<<endl;
            if(book[p]==0)
            {
                book[p]=1;
                dfs(p);
                if(dp1[p]+1>=dp1[pos])
                {
                    dp2[pos]=dp1[pos];
                    dp1[pos]=dp1[p]+1;
                }
                else if(dp1[p]+1>=dp2[pos])
                    dp2[pos]=dp1[p]+1;
                maxn=max(maxn,dp1[pos]+dp2[pos]);
            }
        }
        return;
    }
    void dfs1(int pos,int fath)
    {
        int sum=0;
        for(int i=head[pos];i!=-1;i=x[i].nex)
            if(x[i].v!=fath&&dp1[pos]==dp1[x[i].v]+1) sum++;
        for(int i=head[pos];i!=-1;i=x[i].nex)
        {
            if(x[i].v!=fath)
            {
                if(dp1[x[i].v]+1!=dp1[pos]) dp3[x[i].v]=max(dp1[pos],dp3[pos])+1;
                else if(dp1[x[i].v]+1==dp1[pos]&&sum>1)dp3[x[i].v]=max(dp1[pos],dp3[pos])+1;
                else dp3[x[i].v]=max(dp2[pos],dp3[pos])+1;
                dfs1(x[i].v,pos);
            }
        }
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        n=read();
    //    for(int i=0;i<n;i++) f[i]=i;
        for(int i=1;i<n;i++)
        {
            int u=read(),v=read();
            add(u,v),add(v,u);
        }
        book[0]=1;
        dfs(0);
    //    cout<<maxn<<" ";
        memset(book,0,sizeof(book));
        dfs1(0,-10);
        for(int i=0;i<n;i++)
            if(dp1[i]+max(dp2[i],dp3[i])==maxn) cout<<i<<endl;
        return 0;
    }
    View Code

    周年纪念晚会[loj 10160]

    /*
    0不选1选 
    */ 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return ans*f;
    }
    int a[6001],n;
    struct node{
        int u,v,nex;
    }x[6001];
    int cnt;
    int head[6001],dp[6001][3],t[6001];
    void add(int u,int v)
    {
        x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
    }
    void dfs(int pos)
    {
    //    cout<<pos<<endl;
        dp[pos][0]=0;
        dp[pos][1]=a[pos];
        for(int i=head[pos];i!=-1;i=x[i].nex)
        {
            int p=x[i].v;
            dfs(p);
            dp[pos][0]+=max(0,max(dp[p][0],dp[p][1]));
            dp[pos][1]+=max(0,dp[p][0]);
            
        }
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        n=read();
        memset(dp,0xcf,sizeof(dp));
        for(int i=1;i<=n;i++) a[i]=read();
        for(int i=1;i<n;i++)
        {
            int u=read(),v=read();
            add(v,u);t[u]=1;
        }
        int sry=1;
        while(t[sry]==1) sry++;
        dfs(sry);
        cout<<max(dp[sry][0],dp[sry][1]);
    }
    View Code

    叶子的颜色[loj 10161]

    /*
    dp[pos][0]表示pos涂黑色
    1 表示涂白色
    2 表示不涂
    
    dp[pos][0]+=min(dp[x][0]-1,dp[x][1],dp[x][2])
    1,2同理
    
    -1是因为此点就不需要涂 
    
    预处理见代码 
    */ 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    int m,n,c[6001];
    struct node{
        int u,v,nex;
    }x[20001];
    int head[10001],cnt;
    void add(int u,int v)
    {
        x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
    }
    int book[10001],dp[10001][3];
    void dfs(int pos)
    {
        if(pos>=1&&pos<=m)
        {
            dp[pos][c[pos]]=1;
            dp[pos][1-c[pos]]=dp[pos][2]=2<<30-1;
        }
        else{
            dp[pos][1]=dp[pos][0]=1;
        }
        for(int i=head[pos];i!=-1;i=x[i].nex)
        {
            int t=x[i].v;
            if(book[t]==0)
            {
                book[t]=1;
                dfs(t);
                dp[pos][0]+=min(dp[t][0]-1,min(dp[t][1],dp[t][2]));
                dp[pos][1]+=min(dp[t][1]-1,min(dp[t][0],dp[t][2]));
                dp[pos][2]+=min(dp[t][0],min(dp[t][1],dp[t][2]));
            }
        }
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        n=read(),m=read();
        for(int i=1;i<=m;i++) c[i]=read();
        for(int i=1;i<n;i++)
        {
            int u=read(),v=read();
            add(u,v),add(v,u);
        }
        book[n]=1;
        dfs(n);
        cout<<min(dp[n][0],min(dp[n][1],dp[n][2]));
    }
    View Code

    骑士[loj 10162]

    /*
    断环为链,与没有上司的舞会接下来的十分相似 
    */ 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline long long read()
    {
        long long f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    struct node{
        long long u,v,nex;
    }x[2000001];
    long long cnt;
    long long head[1000001],n,s[1000001],vis[1000001],root,book[1000001],uu,vv;
    void add(long long u,long long v)
    {
        x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
    }
    
    bool flag;
    long long ans;
    void dfs(long long pos,long long fa)
    {
        for(long long i=head[pos];i!=-1;i=x[i].nex)
        {
            long long p=x[i].v;
            if(fa!=p)
            {
                if(vis[p]==0) 
                {
                    vis[p]=1;
                    dfs(p,pos);
                }
                else{
                    flag=true;
                    uu=pos,vv=p;
                }
            }
        }
    }
    long long dp[1000001][2];//0没用,1用 
    long long inf=2<<30-1;
    void dfs_dp(long long pos,long long fa)
    {
    //    cout<<pos<<endl;
        dp[pos][1]=s[pos];
        for(long long i=head[pos];i!=-1;i=x[i].nex)
        {
            long long p=x[i].v;
            if(p!=fa)
            {
                if(p==-inf) continue;
                dfs_dp(p,pos);
                dp[pos][0]+=max(dp[p][0],dp[p][1]);
                dp[pos][1]+=dp[p][0];
            }
        }
        return;
    }
    void work(long long pos)
    {
        memset(dp,0,sizeof(dp));
        flag=false;
        vis[pos]=1;
        dfs(pos,-1);
    //    cout<<uu<<" "<<vv<<endl;
        if(flag==false)
        {
            dfs_dp(pos,-1);
            ans+=max(dp[pos][0],dp[pos][1]);
        }
        else if(flag==true)
        {
            long long maxn=0;
            for(long long i=head[uu];i!=-1;i=x[i].nex)
            {
                long long p=x[i].v;
                if(p==vv) 
                {
                    x[i].v=-inf;
                    break;
                }
            }
            for(long long i=head[vv];i!=-1;i=x[i].nex)
            {
                long long p=x[i].v;
                if(p==uu)
                {
                    x[i].v=-inf;
                    break;
                }
            }
    //        cout<<uu<<" "<<vv<<endl;
            dfs_dp(uu,-1);
    //        return ;
            long long x1=dp[uu][0];
    //        cout<<x1<<endl;
            memset(dp,0,sizeof(dp));
            dfs_dp(vv,-1);
            long long x2=dp[vv][0];
    //        cout<<x2<<endl;
            maxn=max(x1,x2);
            ans+=maxn;
        }
    }
    int main(void)
    {
        memset(head,-1,sizeof(head));
        n=read();
        for(long long i=1;i<=n;i++)
        {
            s[i]=read();
            long long p=read();
            add(i,p),add(p,i);
        }
        for(long long i=1;i<=n;i++)
        {
            if(vis[i]==0)
            {
                work(i);
    //            return 0;
            }
        }
        cout<<ans;
    }
    View Code
  • 相关阅读:
    weblogic详解
    Java实现视频网站的视频上传、视频转码、及视频播放功能(ffmpeg)
    Java上传视频(mencoder)
    input标签type="file"上传文件的css样式
    jQuery系列:选择器
    jQuery系列:Ajax
    Sql Server系列:规范化及基本设计
    Sql Server系列:查询分页语句
    Sql Server系列:通用表表达式CTE
    Sql Server系列:子查询
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/9502543.html
Copyright © 2011-2022 走看看