HDU 4340 Capturing country(树状DP)

来源:互联网 发布:飞控电子显示屏软件 编辑:程序博客网 时间:2024/06/07 03:45

题目大意:

Ant和Bob两只军队要去虏获一个国家,国家中包含了N个城市。

A[j]代表Ant军队攻占city i需要A[I]分钟,同理B[i];

然后同一军队攻占连在一条线上city的时候比如说city j,则只需要A[j]/2;

输出:攻占国家所需的最少时间

题目思路:

用树状DP

dp[i][j][k]=

{

             i:当前城市;

             j:0为当前城市由Ant军队占领,1为Bob军队占领;

             k:0为该条线上全部都为一半花费,1为该条线上存在至少一个付全费city;
}


叶节点的值为

{

            dp[u][0][0]=A[I]/2;

            dp[u][1][0]=B[I]/2;

            dp[u][0][1]=A[I];

            dp[u][1][1]=B[I];

}


对于dp[i][0][0]

{

            设根节点为u,子节点为v.

            初始化dp[u][0][0]=A[u]/2;

            若v被Ant占领,则有:dp[u][0][0]+=dp[v][0][0];

            若v被Bob占领,则有:dp[u][0][0]+=dp[v][1][1];

            所以由此可得转移方程:dp[u][0][0]+=min{dp[v][0][0],dp[v][1][1]};

            同理:dp[u][1][0]+=min{dp[v][0][1],dp[v][1][0];

}


对于dp[i][0][1],分两种情况:

(1)在当前点全花费时

(2)在子孙中全花费

{

            设根节点为u,子节点为v;

(1)

            初始化dp[u][0][1]=A[u];

            若v被Ant占领,则有:dp[u][0][1]+=dp[v][0][0];

            若v被Bob占领,则有:dp[u][0][1]+=dp[v][1][1];

            由此可得转移方程:dp[u][0][1]+=min{dp[v][0][0],dp[v][1][1]};

            同理:dp[u][1][1]+=min{dp[v][0][1],dp[v][1][0]};

(2)

            初始化dp[u][0][1]=A[u]/2;

            此时,要先求出其中最小的dp[v][0][1]-min(dp[v][0][0],dp[v][1][1]),记为ga(ga可能为负)

            然后用dp[u][0][1]+=min{dp[v][0][0],dp[v][1][1]},求出到根节点的全部只用半花费的值,记为sa;

            由此可得转移方程:dp[u][0][1]+=ga+sa;

            同理,可以求出dp[u][1][1];

最后处理:

            答案转移到dp[1][1][1]或者dp[1][0][1]中,取min{dp[1][1][1],dp[1][0][1]}即可得到答案

}

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>using namespace std;#define min(a,b) a<b?a:b#define N 110#define INF 0x7FFFFFFint atime[N],btime[N];vector<int>g[N];int dp[N][2][2];void dfs(int u,int pre){    if( g[u].size()==1 && pre!=-1 )    {        dp[u][0][0] = (atime[u]>>1);        dp[u][1][0] = (btime[u]>>1);        dp[u][0][1] = atime[u];        dp[u][1][1] = btime[u];        return ;    }    int ga=INF,gb=INF;    int sa=0,sb=0;    for(int i=0;i<g[u].size();i++)    {        int v=g[u][i];        if(v==pre)            continue;        dfs(v,u);        int m1=min(dp[v][0][0],dp[v][1][1]);        int m2=min(dp[v][0][1],dp[v][1][0]);        sa += m1;        sb += m2;        ga = min(ga,dp[v][0][1]-m1);        gb = min(gb,dp[v][1][1]-m2);    }    dp[u][0][0] = sa + (atime[u]>>1);    dp[u][1][0] = sb + (btime[u]>>1);    dp[u][0][1] = min(sa + atime[u],ga+sa+(atime[u]>>1));    dp[u][1][1] = min(sb + btime[u],gb+sb+(btime[u]>>1));}int main(){    int i,j,n,u,v;    while(scanf("%d",&n)!=EOF)    {        for(i=0;i<=n;i++)            g[i].clear();        for(i=1;i<=n;i++)            scanf("%d",&atime[i]);        for(i=1;i<=n;i++)            scanf("%d",&btime[i]);        for(i=1;i<n;i++)        {            scanf("%d%d",&u,&v);            g[u].push_back(v);            g[v].push_back(u);        }        dfs(1,-1);        printf("%d\n",min(dp[1][0][1],dp[1][1][1]));    }    return 0;}



原创粉丝点击