zoukankan      html  css  js  c++  java
  • luogu P4362 [NOI2002]贪吃的九头龙

    传送门

    最后基本靠自己的思路秒了这个题吧

    先排除不合法情况

    一个K一个M十分恶心

    然后结合不合法仔细想一想只有m==2的时候小头才会产生花费

    所以问题就变成选择k个点 花费是所有两个端点都选择的边的边权 求最小花费

    按照套路先考虑dp[i][j][0]表示以i为根处理完当前子树 选j个点 0/1表示是否选择根

    所以就可以转移

    注意一棵子树dp的时候滚动数组不要滚错了 实在不行(像我)开一个tmp代替滚动也行

    (memcpy真快)

    Time cost: 65min

    Code:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<queue>
     6 #include<iostream>
     7 #define ms(a,b) memset(a,b,sizeof a)
     8 #define rep(i,a,n) for(int i = a;i <= n;i++)
     9 #define per(i,n,a) for(int i = n;i >= a;i--)
    10 #define inf 2147483647
    11 using namespace std;
    12 typedef long long ll;
    13 typedef double D;
    14 #define eps 1e-8
    15 ll read() {
    16     ll as = 0,fu = 1;
    17     char c = getchar();
    18     while(c < '0' || c > '9') {
    19         if(c == '-') fu = -1;
    20         c = getchar();
    21     }
    22     while(c >= '0' && c <= '9') {
    23         as = as * 10 + c - '0';
    24         c = getchar();
    25     }
    26     return as * fu;
    27 }
    28 //head
    29 const int N = 305;
    30 int n,m,K;
    31 int head[N],nxt[N<<1],mo[N<<1],cst[N<<1],cnt;
    32 void _add(int x,int y,int w) {
    33     mo[++cnt] = y;
    34     cst[cnt] = w;
    35     nxt[cnt] = head[x];
    36     head[x] = cnt;
    37 }
    38 void add(int x,int y) {
    39     int w = read();
    40     _add(x,y,w),_add(y,x,w);
    41 }
    42 
    43 int dp[N][N][2];
    44 int tmp[N][2];
    45 void dfs(int x,int f) {
    46     dp[x][0][0] = dp[x][1][1] = 0;
    47     for(int i = head[x];i;i = nxt[i]) {
    48         int sn = mo[i];
    49         if(sn == f) continue;
    50         dfs(sn,x);
    51         memcpy(tmp,dp[x],sizeof(tmp));
    52         ms(dp[x],63);
    53         rep(j,0,K) rep(t,0,j) {
    54             dp[x][j][0] = min(dp[x][j][0],dp[sn][t][0] + tmp[j-t][0] + (m == 2) * cst[i]);
    55             dp[x][j][0] = min(dp[x][j][0],dp[sn][t][1] + tmp[j-t][0]);
    56             dp[x][j][1] = min(dp[x][j][1],dp[sn][t][1] + tmp[j-t][1] + cst[i]);
    57             dp[x][j][1] = min(dp[x][j][1],dp[sn][t][0] + tmp[j-t][1]);
    58         }
    59     }
    60 }
    61 
    62 int main() {
    63     n = read(),m = read(),K = read();
    64     if(n-m-K+1 < 0) {
    65         puts("-1");
    66         return 0;
    67     }
    68     rep(i,2,n) add(read(),read());
    69     ms(dp,63);
    70     dfs(1,1);
    71     printf("%d
    ",dp[1][K][1]);
    72     return 0;
    73 }
    > 别忘了 总有人在等着你
  • 相关阅读:
    GTest交流与经验总结
    linux i2c驱动架构-dm368 i2c驱动分析
    在不同编译环境中如何使用sleep()函数
    Android应用之基本的组件(一)
    Java Arrays Tutorial (3)
    ASP.NET中操作SQL数据库
    安卓开发06:布局-线性布局 LinearLayout
    在开发 ExtJS 应用程序常犯的 10 个错误
    每天4个linux命令--步骤一
    获取CPU序列号
  • 原文地址:https://www.cnblogs.com/yuyanjiaB/p/9911318.html
Copyright © 2011-2022 走看看