zoukankan      html  css  js  c++  java
  • POJ 1770 树形DP

    题意:

    容器中有 n 种原子,现提供 m 种光子,这 n 种原子中能量之差等于提供的 m 种光子之一所具有的能量,就认为这两种原子是处在容器在是危险的,现在要求取走一些原子,使得容器中的原子处在一块是安全的,同时要求剩下的原子的能量和最大。

     

    思路:

    很明显的树形dp,每两个处于会产生危险的原子连一条无向边,注意建图完了可能是一个森林!

    PS:不会有环么?我AC了以后才发现这个问题。。。网上都没提这事,不知道我没完全理解题?

     

    View Code
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <iostream>
     5 #include <cmath>
     6 #include <map>
     7 
     8 #define N 10000
     9 #define M 100000
    10 
    11 using namespace std;
    12 
    13 map<int,int> mp;
    14 
    15 int head[N],to[M],next[M],a[N],b[N],cnt,num,n,m,tc[N],dp[N][2];
    16 bool vis[N];
    17 
    18 inline void add(int u,int v)
    19 {
    20     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;
    21 }
    22 
    23 void read()
    24 {
    25     mp.clear();
    26     memset(head,-1,sizeof head);cnt=0;
    27     num=0;
    28     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    29     for(int i=1;i<=m;i++) scanf("%d",&b[i]);
    30     for(int i=1;i<=n;i++)
    31         for(int j=i+1;j<=n;j++)
    32             for(int k=1;k<=m;k++)
    33                 if(abs(a[i]-a[j])==b[k])
    34                 {
    35                     if(mp[a[i]]==0) {mp[a[i]]=++num;tc[num]=a[i];}
    36                     if(mp[a[j]]==0) {mp[a[j]]=++num;tc[num]=a[j];}
    37                     int ta=mp[a[i]],tb=mp[a[j]]; 
    38                     add(ta,tb),add(tb,ta);
    39                 }
    40 }
    41 
    42 void find(int u,int fa)
    43 {
    44     vis[u]=true;
    45     for(int i=head[u];~i;i=next[i])
    46         if(to[i]!=fa) find(to[i],u);
    47         
    48     dp[u][1]=tc[u];dp[u][0]=0;
    49     for(int i=head[u];~i;i=next[i])
    50         if(fa!=to[i])
    51         {
    52             dp[u][0]+=max(dp[to[i]][1],dp[to[i]][0]);
    53             dp[u][1]+=dp[to[i]][0];
    54         }
    55 }
    56 
    57 void go()
    58 {
    59     memset(dp,0x8f,sizeof dp);
    60     memset(vis,0,sizeof vis);
    61     int ans=0;
    62     for(int i=1;i<=num;i++)
    63         if(!vis[i])
    64         {
    65             find(i,-1);
    66             ans+=max(dp[i][0],dp[i][1]);
    67         }
    68     printf("%d\n",ans);
    69 }
    70 
    71 int main()
    72 {
    73     while(scanf("%d%d",&n,&m),n||m)
    74     {
    75         read();
    76         go();
    77     }
    78     return 0;
    79 }

     

     

    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    学习:Intents和Intent Filters(理论部分)
    天书夜读:从汇编语言到Windows内核编程笔记(1)
    学习:Intents和Intent Filters(实例部分)
    寒江独钓(1):内核数据类型和函数
    寒江独钓(2):串口的过滤
    学习:了解WDK目录
    Nginx 414 RequestURI Too Large 海口
    Ansible 批量修改密码 海口
    记一次node进程无法kill 问题 海口
    Vue学习心得新手如何学习Vue(转载)
  • 原文地址:https://www.cnblogs.com/proverbs/p/2711756.html
Copyright © 2011-2022 走看看