hdu 1011
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1011
题目大意:一棵树,有n个节点,根节点编号为1,即入口,每个节点有一些Bugs及Brains,现在有m个士兵,一个士兵能打20个Bugs,让你用这些士兵去攻打这个Cave,最多能获得多少Brains。
思路:好吧,我承认我做了很久。状态方程还是比较简单的,d[ u ][ i ] = max(d[ u ][ i ] , d[ v ][ j ]+d[ u ][ i-j ]) , j<=i ; 细节啊,处理了半天,跑出样例了,一交,还是WA,看了半天没看出来。后来一看DISCUSS,原来有一个trick,发现如果一个洞穴的Bugs = 0,那么也需要至少派一个士兵走过,但可以不停留。有一组数据:
5 2
0 1 0 1 0 5 0 1 0 2 1 2 1 3 2 4 2 5
答案是9!不相信自己画画就知道了。 = =
知道哪里有问题,想了想还不知道怎么改。。 再次去网上看了一下,加了两句话:
d[u][1]=max(d[u][1],d[u][0]);
d[u][0]=-INF;
唉,还是不行啊,树形DP继续练吧!
代码如下:
#include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int MAXN = 111 ; const int INF = 0X0FFFFFFF ; struct Cave { int bugs,bra; } cave[MAXN]; int vis[MAXN]; int n,m; vector <int> G[MAXN]; int d[MAXN][MAXN]; void dfs(int u) { vis[u]=1; for(int i=0;i<=m;i++) d[u][i]=-INF; d[u][cave[u].bugs] = cave[u].bra; for(int i=0;i<G[u].size();i++) { int v = G[u][i]; if(!vis[v]) { dfs(v); //printf("u = %d,v = %d\n" ,u,v); for(int j = m;j>=cave[u].bugs;j--) for(int k = 0;k<=j;k++) { d[u][j] = max(d[u][j],d[v][k]+d[u][j-k]); //printf("d[%d][%d] = %d\n",u,j,d[u][j]); } } } d[u][1]=max(d[u][1],d[u][0]); d[u][0]=-INF; } int main() { while(~scanf("%d%d",&n,&m)) { if(n==-1&&m==-1) break; for(int i=1;i<=n;i++) { scanf("%d%d",&cave[i].bugs,&cave[i].bra); cave[i].bugs = (cave[i].bugs+19)/20; } int a,b; for(int i=1;i<=n;i++) G[i].clear(); for(int i=1;i<n;i++) { scanf("%d%d",&a,&b); G[a].push_back(b); G[b].push_back(a); } memset(vis,0,sizeof(vis)); dfs(1); int ans=0; for(int i=1;i<=m;i++) ans=max(ans,d[1][i]); printf("%d\n",ans); } return 0; }