hdu1011 Starship Troopers(树形dp)

来源:互联网 发布:炉石传说 朝神 知乎 编辑:程序博客网 时间:2024/05/04 15:36

开始尝试写写博客

树形dp,111数组大小过不了runtime error好久以为是自己代码错了,赞这里写图片描述

对一个点n,最多派出m个士兵,得到的最大可能保存在dp[n][m]
计算方法是遍历所有子节点进行背包。

第一次做这种稍微复杂的题目做了一天,太鸡了得多练

顺便学到了无权图可以用vector保存邻接链表,挺好挺简洁。有权图应该也可以用pair

#include <iostream>#include <cstring>#include <cmath>#include <algorithm>#include <queue>#include <stack>#include <map>#include <fstream>#define NINF -999999999#define ll long longusing namespace std;struct point{    int t;    int brain;    int edgelist;}caves[1111];struct edge{    int to;    int next;}edges[1111];int TotalEdge;void AddEdge(int u,int v){    edges[TotalEdge].to=v;    edges[TotalEdge].next=caves[u].edgelist;    caves[u].edgelist=TotalEdge++;}int n,m;int dp[1111][1111];bool visited[1111];void solve2(int n)      //解出以某个节点为根的最多的possibility dp[n][0]到dp[n][m];{    for (int i=caves[n].t;i<=m;i++) //初始化        dp[n][i]=caves[n].brain;    for (int i=0;i<caves[n].t;i++)        dp[n][i]=0;    visited[n]=true;    for (int tmp=caves[n].edgelist;tmp!=0;tmp=edges[tmp].next)//遍历所有的子树    {        int tar(edges[tmp].to);        if (visited[tar])            continue;        solve2(tar);        for (int i=m;i>=caves[n].t;i--)        {            for (int j=1;j<=i-caves[n].t;j++)                dp[n][i]=max(dp[n][i],dp[n][i-j]+dp[tar][j]);        }    }}int main(){    cin.sync_with_stdio(false);    while (cin>>n>>m,n!=-1)    {        TotalEdge=1;        for (int i=1;i<=n;i++)        {            cin>>caves[i].t>>caves[i].brain;            //caves[i].t=(caves[i].t%20 ? 1 : 0) + caves[i].t / 20 ;            caves[i].t=(caves[i].t+19)/20;//其他人代码看到的一种比较方便的计算类似情况的方法            caves[i].edgelist=0;            visited[i]=false;        }        for (int i=0;i<n-1;i++)        {            int tp1,tp2;            cin>>tp1>>tp2;            AddEdge(tp1,tp2);            AddEdge(tp2,tp1);        }        if (m==0)        {            cout<<0<<endl;            continue;        }        solve2(1);        cout<<dp[1][m]<<endl;    }    return 0;}
0 0
原创粉丝点击