zoukankan      html  css  js  c++  java
  • bzoj 4711 小奇挖矿 —— 树形DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4711

    就是树形DP,然而也想了半天才把转移想清楚;

    f[x][j][0] 表示 x 去上面 j 步的仓库,f[x][j][1] 表示 x 去子树内下去 j 步的仓库而且整个子树都算好了;

    f[x][j][0] 就是 d[j] 加上儿子们的 f[u][...][1] 与 f[u][j+1][0] 的最小值;

    f[x][j][1] 就是选一个儿子加它的 f[u][j-1][1],其它儿子是 f[u][...][1] 与 f[u][j+1][0] 的最小值;

    f[x][0][1] 要特殊处理一下;

    然后一交秒WA,又改了改,似乎也没改什么,就A了...总之注意边界。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int const xn=205,inf=0x3f3f3f3f;
    int n,K,d[xn],ans,f[xn][xn][2],mn[xn];
    int hd[xn],ct,nxt[xn<<1],to[xn<<1];
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct;}
    void dfs(int x,int fa)
    {
      for(int i=hd[x],u;i;i=nxt[i])
        {
          if((u=to[i])==fa)continue;
          dfs(u,x);
        }
      for(int j=0;j<n;j++)
        {
          if(!j)f[x][j][0]=K;
          else f[x][j][0]=d[j];
          for(int i=hd[x],u;i;i=nxt[i])
            {
              if((u=to[i])==fa)continue;
    //          for(int k=0;k<n;k++)ret=min(ret,f[u][k][1]);
              int ret=min(mn[u],f[u][j+1][0]);
              f[x][j][0]+=ret;
            }
          if(!j)
            {
              f[x][j][1]=K;
              for(int i=hd[x],u;i;i=nxt[i])
                {
                  if((u=to[i])==fa)continue;
                  int ret=min(f[u][1][0],mn[u]);
    //              for(int k=0;k<n;k++)ret=min(ret,f[u][k][1]);
                  f[x][j][1]+=ret;
                }
            }
          else
            {
              f[x][j][1]=inf;
              for(int i=hd[x],v;i;i=nxt[i])
                {
                  if((v=to[i])==fa)continue;
                  int r=f[v][j-1][1]+d[j];
                  for(int l=hd[x],u;l;l=nxt[l])
                    {
                      if((u=to[l])==fa||u==v)continue;
                      int ret=min(f[u][j+1][0],mn[u]);
    //                  for(int k=0;k<n;k++)ret=min(ret,f[u][k][1]);
                      r+=ret;
                    }
                  f[x][j][1]=min(f[x][j][1],r);
                }
            }
            mn[x]=min(mn[x],f[x][j][1]);
        }
    }
    int main()
    {
      n=rd(); K=rd();
      for(int i=1;i<n;i++)d[i]=rd();
      for(int i=1,x,y;i<n;i++)
        {
          x=rd(); y=rd();    
          add(x,y); add(y,x);
        }
      memset(f,0x3f,sizeof f);
      memset(mn,0x3f,sizeof mn);
      dfs(1,0); ans=f[1][0][0];
      for(int j=0;j<n;j++)ans=min(ans,f[1][j][1]);
      printf("%d
    ",ans);
      return 0;
    }
  • 相关阅读:
    ADO.NET基础学习 二(Command对象)
    如何使ElementUI中的el-dropdown传入多参数
    Vue router Element 重复点击导航路由报错解决方法
    vue-svgicon基本使用
    js 两个相等的数组,修改其中一个怎么做到不改变另外一个
    LocalStorage存储JSON对象
    js取整数、取余数的方法
    JS正则截取两个字符串之间及字符串前后内容的方法
    Vuetify 表单规则验证
    JS正则表达式
  • 原文地址:https://www.cnblogs.com/Zinn/p/9754533.html
Copyright © 2011-2022 走看看