• HDU4340 Capturing a country DP


    自己原来写的两个维度的DP有错,看了半天这个大牛的blog。http://blog.csdn.net/cyberzhg/article/details/7840922

    题意:A军队和B军队要一起占领一个国家,城市和城市之间有一些双向边(但是没有环)。A军队要占领i城市需要a[i]的代价,B军队需要b[i]的代价。

            若果A军队占领了i城市,i城市和j城市相邻,则A军队占领j城市只要a[i]/2的代价,B军队同理。问两个军队一起占领所有城市所需要花费的最小代价是多少。

    解题过程上上述解题报告,再加几点自己的理解

    f[i][0][0]表示的是以i用A军队进行进攻,且其所有选A军队的孩子选择半价的代价。

    f[i][0][0] 和f[i][1][0]是一个辅助状态。

    f[i][0][1]和f[i][1][1]才是正解。

    对于”选择一个儿子付出代价,这个代价必须最小:min(dp[v][0][1] - min(dp[v][0][0], dp[v][1][0]));“

    这个转移方程的理解要从dp[u][0][1] = min(SA + A[u], SA + A[u] / 2 + DA);来分析

    SA+A[u]/2+DA=sum{min(dp[v][0][0], dp[v][1][1])}+A[u]/2+min(dp[v][0][1] - min(dp[v][0][0], dp[v][1][0]));

    注意黄色表示的两个量相同。

      假设min(dp[v][0][0],dp[v][1][1])= tmp[v];

    则表达式可以清楚得写成SA+A[u]/2+DA=tm[1]+tmp[2]+tmp[3]+...tmp[sonSize]+min(dp[v][0][1]-tmp[j])   +A[u]/2;

                                                             =min{dp[v][0][1]+tmp[1]+tmp[2]+tmp[3]+...tmp[j-1]+tmp[j+1]+...+tmp[sonSize}+ A[u]/2;

                                                           可以理解成已知一个数列的加和sum,现在改变其中a[i]成为p。。则新的加和为sum-a[i]+p;

    方程长确实比较不喜欢看。

         代码实现的时候死在#define min(a,b) ((a)>(b)? (b):(a))上面了,我竟然不知道。。好吧,引以为戒。。

    #include <stdio.h>
    #include <string.h>
    #define MAXN 105
    #define min(a,b) ((a)>(b)? (b):(a))
    int f[MAXN][2][2];
    int a[MAXN];
    int b[MAXN];
    int map[MAXN][MAXN];
    int dp(int i, int j,int k,int fa)
    {
        if (f[i][j][k] != -1)
            return f[i][j][k];
        if (map[i][0] == 1 && fa != -1)
        {
    
            f[i][0][0]=a[i]/2;
            f[i][0][1]=a[i];
            f[i][1][0]=b[i]/2;
            f[i][1][1]=b[i];
            return f[i][j][k];
        }
        int son;
        int SA=0;
        int SB=0,DA=1000000000,DB=1000000000;
        //  if (i == 2) printf("!!!");
        for (int p = 1; p <= map[i][0]; p++)
            if (map[i][p] != fa)
            {
                son=map[i][p];
                SA+=min(dp(son,0,0,i),dp(son,1,1,i));
                SB+=min(dp(son,1,0,i),dp(son,0,1,i));
                DA=min(DA,dp(son,0,1,i)-min(dp(son,0,0,i),dp(son,1,1,i)));
                DB=min(DB,dp(son,1,1,i)-min(dp(son,1,0,i),dp(son,0,1,i)));
            }
        f[i][0][0]=SA+a[i]/2;
        f[i][1][0]=SB+b[i]/2;
        f[i][0][1]=min(SA+a[i],SA+a[i]/2+DA);
        f[i][1][1]=min(SB+b[i],SB+b[i]/2+DB);
        
    }
    int main()
    {
        int i,j,m,n;
        int x,y,k;
        while (scanf("%d", &n) != EOF)
        {
            for (i = 1; i <= n; i++)
                scanf("%d", &a[i]);
            for (i = 1; i <=n; i++)
                scanf("%d", &b[i]);
            memset(map,0,sizeof(map));
            memset(f,-1,sizeof(f));
            for (i =  1; i <n; i++)
            {
                scanf("%d%d",&x,&y);
                map[x][++map[x][0]]=y;
                map[y][++map[y][0]]=x;
            }
            printf("%d
    ",min(dp(1,0,1,-1),dp(1,1,1,-1)));
        }
        return 0;
    }
  • 相关阅读:
    详细解读 DispatcherServlet 初始化过程(带时序图)
    从源码分析ContextLoaderListener的加载过程(带时序图)
    SpringMVC自带Cron定时器Demo及常见问题
    win7系统用sqlyog连接不上docker启动的mysql数据库
    使用maven-Jetty9-plugin插件运行第一个Servlet
    Maven项目+内嵌tomcat+Servlet
    Maven依赖的scope属性(附官方文档)
    使用 Intellij IDEA 新建一个 Servlet 项目
    在 Tomcat 上部署你的第一个 Servlet 应用
    关于JAVA的垃圾回收机制
  • 原文地址:https://www.cnblogs.com/six-god/p/3362576.html
Copyright © 2020-2023  润新知