hdu 1011 Starship Troopers_树状dp
题意:给你一棵树(必须从根节点出发),每个节点上都有bug和value,你有m个骑士,每个骑士能消灭20个bug,你必须消灭该节点的全部bug才能拿到该节点的value,问最多能拿到value是多少.
思路:典型的背包dp , dp[n][m]=max(dp[n][m-x]+value,dp[n][m])
#include<iostream> #include<cstdio> using namespace std; #define N 110 #define INF 999999999 struct node { int v,next; }edge[N<<1]; int adj[N],vis[N],room[N][2],dp[N][N],edgeNum; int max(int a,int b){return a>b?a:b;} void AddEdge(int u,int v) { edge[edgeNum].v=v,edge[edgeNum].next=adj[u],adj[u]=edgeNum++; edge[edgeNum].v=u,edge[edgeNum].next=adj[v],adj[v]=edgeNum++; } void init() { memset(vis,0,sizeof(vis)); memset(adj,-1,sizeof(adj)); memset(dp,0,sizeof(dp)); edgeNum=0; } void dfs(int u,int m) { int num=room[u][0]/20,i,j,k; if(room[u][0]%20)//bug多于二十的倍数当然要多一个骑士消灭bug num++; vis[u]=1; for(i=num;i<=m;i++) dp[u][i]=room[u][1];//加上该节点的价值 for(i=adj[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(!vis[v]) { dfs(v,m); for(j=m;j>=num;j--) { for(k=1;j+k<=m;k++) if(dp[v][k]) dp[u][k+j]=max(dp[u][k+j],dp[u][j]+dp[v][k]);//背包求最优价值 } } } } int main() { int n,m; int i,u,v; while(scanf("%d%d",&n,&m)) { if(n==-1&&m==-1) break; init(); for(i=1;i<=n;i++) scanf("%d%d",&room[i][0],&room[i][1]); for(i=1;i<n;i++) { scanf("%d%d",&u,&v); AddEdge(u,v);//单向 } if(m==0)//没有骑士 { printf("0\n"); continue; } dfs(1,m);//必须从节点1开始 printf("%d\n",dp[1][m]); } return 0; }
不怕路长,只怕心老.