hdu 4276 The Ghost Blows Light(2012 ACM/ICPC Asia Regional Changchun Online )

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4276

题目大意:对于一个每条边有耗时len,且每个点有财富值,问从1到n点在规定的T时间内,最多能收集多少财富,如果在规定的T时间内不能到达n则输出“ **** ”;

关键状态方程:

temp = edge[i].len*2;

for(j = T; j >= temp; j--)
                for(k = temp; k <= j  ; k++)
                dp[root][j]=max(dp[root][j],dp[root][j-k] + dp[edge[i].node][k-temp]);

解题思路一:可以先将1到n的路径全部耗时全改为0,同时将T减去该路径上的耗时总和即T-=sum!dp[1][T]即为答案!

#include<stdio.h>
#include<string.h>
#define MAXN 105
#define MAXT 505
int dp[MAXN][MAXT];
int head[MAXN], val[MAXN], path[MAXN], tdp[MAXT],next[MAXN], cnt,  N, T,sum;
struct Edge{
    int len;
    int node;
    int next;
}edge[MAXN*2];
void add(int a, int b, int c)
{
    edge[cnt].node = b; edge[cnt].len = c; edge[cnt].next = head[a];head[a]=cnt++;
    edge[cnt].node = a; edge[cnt].len = c; edge[cnt].next = head[b];head[b]=cnt++;
    return ;
}
int max(int a, int b)
{
    return (a>b)?a:b;
}
bool find(int rt,int fa)  
{  
    if(rt == N )return 1;  
    for(int i = head[rt];i != -1;i = edge[i].next)  
    {  
        int son = edge[i].node;  
        if(son == fa) continue;  
        if( find(son,rt) )  
        {  
            sum += edge[i].len;  
            edge[i].len = 0;  
            return 1;  
        }  
    }  
    return 0;  
}  
int dfs(int root, int fa)
{
    int i,j,k, temp;
    for(i = 0; i <= T; i++)dp[root][i] = val[root];
    for(i = head[root]; ~i; i=edge[i].next)
    {
        if(edge[i].node != fa)
        {
            dfs(edge[i].node, root);
            temp = edge[i].len*2;
            for(j = T; j >= temp; j--)    for(k = temp; k <= j  ; k++)
                dp[root][j]=max(dp[root][j],dp[root][j-k] + dp[edge[i].node][k-temp]);
        }
    }
    return 0;
}
int main()
{
    int i, a, b, c;
    while(~scanf("%d%d",&N,&T))
    {
        memset(head,-1,sizeof(head));
        for(cnt =0, i = 1; i < N; i++)
        {
            scanf("%d%d%d",&a, &b, &c);
            add(a, b, c);
        }
        for(i = 1; i <= N; i++)
            scanf("%d",&val[i]);
        sum = 0;
        find(1,-1);
         if(sum>T)
             printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");
         else
         {
             //memset(dp,0,sizeof(dp));
             T -= sum;
             dfs(1, -1);
            printf("%d\n",dp[1][T]);
         }
    }
    return 0;
}

思路二:可以先将该路径上的总获得值保存在ans之中,再另外开一个数组tdp,对该路径以外直接相连的点背包一次就ok啦!ans+tdp[T]为所得结果!

此种解法需要注意的是,必须T先将路径上的所耗时间总和减掉sum,再进行dp,否则会超时,我在这里超时了好久,囧!

这思路大复杂度和上面那个差不多!稍微弱一点点!

#include<stdio.h>
#include<string.h>
#define MAXN 115
#define MAXT 515
int dp[MAXN][MAXT];
int head[MAXN], val[MAXN], path[MAXN], tdp[MAXT], cnt,  N, T;
struct Edge{
    int len;
    int node;
    int next;
}edge[MAXN*2];
void add(int a, int b, int c)
{
    edge[cnt].node = b; edge[cnt].len = c; edge[cnt].next = head[a];head[a]=cnt++;
    edge[cnt].node = a; edge[cnt].len = c; edge[cnt].next = head[b];head[b]=cnt++;
    return ;
}
int max(int a, int b)
{
    return (a>b)?a:b;
}
int find(int root, int fa)
{
   int i;
    if(root == N)return 1;
    for(i = head[root]; ~i; i=edge[i].next)
    {
        if(edge[i].node != fa)
        {
            if(find(edge[i].node, root))
			{
                path[++cnt] = i;
				return 1;
			}
        }
    }
    return 0;
}
int dfs(int root, int fa)
{
    int i,j,k, temp;
    for(i = 0; i <= T; i++)dp[root][i] = val[root];
    for(i = head[root]; ~i; i=edge[i].next)
    {
        if(edge[i].node != fa)
        {
            dfs(edge[i].node, root);
            temp = edge[i].len*2;
            for(j = T; j >= temp; j--)
				for(k = temp; k <= j  ; k++)
                dp[root][j]=max(dp[root][j],dp[root][j-k] + dp[edge[i].node][k-temp]);
        }
    }
    return 0;
}
int main()
{
    int node,sum, ans,i,j, fa, a, b, c,temp,t,k;
    while(~scanf("%d%d",&N,&T))
    {
        memset(head,-1,sizeof(head));
        for(cnt =0, i = 1; i < N; i++)
        {
            scanf("%d%d%d",&a, &b, &c);
            add(a, b, c);
        }
        for(i = 1; i <= N; i++)
            scanf("%d",&val[i]);
        cnt = 0;
         find(1,-1);
         for(i = cnt, sum = 0, ans = val[1]; i > 0; i--)
            sum += edge[path[i]].len,ans +=val[edge[path[i]].node] ;
         if(sum>T)
             printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");
         else
         {
             T -= sum;
			 dfs(1, -1);
             memset(tdp,0,sizeof(tdp));
			 path[0]=-1;
            for(i = cnt,node = 1,fa = -1; i > -1; i--)
            {
                for(t = head[node]; ~t; t = edge[t].next)
                {
                    if((t != path[i])&&(edge[t].node!=fa))
                    {
                            temp = edge[t].len * 2;
                            for(j = T; j >= temp; j--)
                                for(k = temp; k <= j  ; k++)
									tdp[j]=max(tdp[j],tdp[j-k] + dp[edge[t].node][k-temp]);
                    }
                }
                fa = node;
                node=edge[path[i]].node;
            }
            ans += tdp[T];
            printf("%d\n",ans);
         }
    }
    return 0;
}

/*
3 3
1 3 1
3 2 1
1 2 3

7 11
1 2 2 
2 3 2
2 7 3
3 4 3
7 5 1
5 6 2
1 2 3 4 5 6 7


7 11
1 2 2
2 3 2
2 7 3
3 4 3
7 5 1
5 6 2
1 2 7 4 5 6 7


2 10
1 2 4
10 10
5 10
1 2 2 
2 3 2
2 5 3
3 4 3
1 2 3 4 5
1 10
10

*/



你可能感兴趣的:(hdu 4276 The Ghost Blows Light(2012 ACM/ICPC Asia Regional Changchun Online ))