• poj1947


    这道题挺有意思的,标签是树形DP加背包。

    一眼看过去其实状态挺好想的,显然根为x的子树取j个点可以形成最优子问题的解。

    不过这道题的转移方程有点特殊,因为在不取某一个点的时候不是单纯的不去处理他就好了,而是也会对当前这个状态的值产生影响。

    所以需要提前先取一个值表示取到这棵子树的时候不取这个点,然后再去比较取了这个点的值。

    转移方程为: 首先取一个tmp=dp[x][j]+1;表示以x为根的子树取了j个点,但是当前扫到这棵子树不取点

      然后枚举这棵子树取的点数 tmp=min(tmp,dp[v][j-k]+dp[x][k]);

    最后把tmp值赋给dp即可

    因为标签是加了背包的嘛,所以实际做的时候应该能察觉到,这题枚举状态的时候也就是x为根的树取j个点的时候,j的枚举需要从大到小,以避免同一棵子树一直被取。

    下附代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 using namespace std;
     5 const int INF=0X3f3f3f3f;
     6 int head[155],Next[305],to[305],tot=0,n,p,flag[155],dp[155][155];
     7 void add(int a,int b){
     8     Next[tot]=head[a],to[tot]=b;
     9     head[a]=tot++;
    10 }
    11 void dfs(int x,int pre){
    12     dp[x][1]=0;
    13     for (int i=head[x]; i!=-1; i=Next[i]){
    14         int v=to[i];
    15         if (v!=pre){
    16             dfs(v,x);
    17             for (int j=p; j>0; j--){
    18                 int tmp=dp[x][j]+1;
    19                 for (int k=1; k<j; k++){
    20                     if (dp[v][j-k]+dp[x][k]<tmp){
    21                         tmp=dp[v][j-k]+dp[x][k];
    22                     }
    23                 }
    24                 dp[x][j]=tmp;
    25             }
    26         }
    27     }
    28 }
    29 int main(){
    30     while (scanf("%d%d",&n,&p)!=EOF){
    31         tot=0;
    32         memset(dp,INF,sizeof(dp));
    33         memset(flag,0,sizeof(flag));
    34         for (int i=1; i<=n; i++) head[i]=-1;
    35         for (int i=1; i<n; i++){
    36             int a,b;
    37             scanf("%d%d",&a,&b);
    38             flag[b]=1;
    39             add(a,b);
    40             add(b,a);
    41         }
    42         int root;
    43         for (int i=1; i<=n; i++){
    44             if (!flag[i]) {
    45                 root=i;
    46                 break;
    47             }
    48         }
    49         dfs(root,-1);
    50         int res=dp[root][p];
    51         for (int i=1; i<=n; i++){
    52             if (res>dp[i][p]+1)
    53                 res=dp[i][p]+1;
    54         }
    55         printf("%d
    ",res);
    56     }
    57     return 0;
    58 }
    View Code
  • 相关阅读:
    HDU 1058 Humble Numbers
    HDU 1160 FatMouse's Speed
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1003 Max Sum
    HDU 1297 Children’s Queue
    UVA1584环状序列 Circular Sequence
    UVA442 矩阵链乘 Matrix Chain Multiplication
    DjangoModels修改后出现You are trying to add a non-nullable field 'download' to book without a default; we can't do that (the database needs something to populate existing rows). Please select a fix:
    opencv做的简单播放器
    c++文件流输入输出
  • 原文地址:https://www.cnblogs.com/i-caigou-TT/p/13860558.html
Copyright © 2020-2023  润新知