zoukankan      html  css  js  c++  java
  • POJ 1682 多重DP

    题意:

    有三个相互隔离的河岸X,Y,Z,每个岸上分别有n,m,p个部落,每个河岸上的部落之间是敌对的(即同一个河岸上的部落之间不能连通),然而,位于不同河岸上的任意两个部落之间都是友好的,现在请你在部落之间搭建桥梁(不能交叉),每座桥的费用是两部落的海拔差的绝对值,求:使得每一个部落都能与至少一个他的友好部落连通 的桥的总费用。

    友情提示:注意坐标的顺序

    PS:自己连蒙带猜的题意,AC了。。O(∩_∩)O~

    思路:

    对于三个河岸,两两做一遍n^2的dp,再把三个dp结合起来做一遍dp(其实就是找最值)

    河岸分布图:

    x河岸从左向右部落编号是增大的,y、z河岸自己看吧~

    借用了LYD神犇的一张图片嘿嘿~

    xz[i][j]表示河岸x的i与河岸z的j之间要修一座桥,且满足x河岸的i~n和z河岸的1~j与对岸连通

    xy[i][j]表示河岸x的i与河岸y的j之间要修一座桥,且满足x河岸的i~n和y河岸的1~j与对岸连通

    yz[i][j]表示河岸y的i与河岸z的j之间要修一座桥,且满足y河岸的i~n和z河岸的1~j与对岸连通

    按照上边那样做三遍dp就完成了这道题目的第一步

    接下来,就是将这三个数组整合在一起得到我们需要的答案了!

    首先我们要思考整合的方式:(先告诉你4种类型共有8种情况,先自己想想再往下看)

    以下图片黑线代表一条河岸,黑线与红线的交点是一个部落

    第一种(封闭式,共一种):

    第二种(一头开口式,共三种):

    第三种(两头开口式,共三种):

    第四种(开放式,共一种):

    如果你还是看不懂的话,只能说明我的表达能力有问题。。。

    上代码了~

    View Code
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <iostream>
     5 #include <cmath>
     6 
     7 #define N 150
     8 
     9 using namespace std;
    10 
    11 int n,m,p,a[N],b[N],c[N],xz[N][N],xy[N][N],yz[N][N],ans,tt;
    12 
    13 void read()
    14 {
    15     scanf("%d%d%d",&m,&n,&p);
    16     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    17     for(int i=1;i<=m;i++) scanf("%d",&b[i]);
    18     for(int i=1;i<=p;i++) scanf("%d",&c[i]);
    19     for(int i=0;i<N;i++)
    20         for(int j=0;j<N;j++)
    21             xz[i][j]=xy[i][j]=yz[i][j]=999999;
    22     ans=999999;
    23 }
    24 
    25 void go()
    26 {
    27     xz[0][p+1]=0;
    28     for(int i=1;i<=n;i++)
    29         for(int j=p;j>=1;j--)
    30             xz[i][j]=min(min(xz[i-1][j+1],xz[i-1][j]),xz[i][j+1])+abs(a[i]-c[j]);
    31     xy[n+1][0]=0;
    32     for(int i=n;i>=1;i--)
    33         for(int j=1;j<=m;j++)
    34             xy[i][j]=min(min(xy[i+1][j-1],xy[i+1][j]),xy[i][j-1])+abs(a[i]-b[j]);
    35     yz[m+1][0]=0;
    36     for(int i=m;i>=1;i--)
    37         for(int j=1;j<=p;j++)
    38             yz[i][j]=min(min(yz[i+1][j-1],yz[i+1][j]),yz[i][j-1])+abs(b[i]-c[j]);
    39     for(int i=0;i<=n+1;i++)
    40         for(int j=0;j<=m+1;j++)
    41             for(int k=0;k<=p+1;k++)
    42             {
    43                 ans=min(ans,xy[i][j]+xz[i][k]+yz[j][k]);
    44                 
    45                 ans=min(ans,xy[i][j]+xz[i][k]+yz[j+1][k]);  
    46                 ans=min(ans,xy[i+1][j]+xz[i][k]+yz[j][k]);  
    47                 ans=min(ans,xy[i][j]+xz[i][k+1]+yz[j][k]);
    48                   
    49                 ans=min(ans,xy[i+1][j]+xz[i][k]+yz[j+1][k]);  
    50                 ans=min(ans,xy[i][j]+xz[i][k+1]+yz[j+1][k]);  
    51                 ans=min(ans,xy[i+1][j]+xz[i][k+1]+yz[j][k]);
    52                   
    53                 ans=min(ans,xy[i+1][j]+xz[i][k+1]+yz[j+1][k]);
    54             }
    55     printf("%d\n",ans);
    56 }
    57 
    58 int main()
    59 {
    60     scanf("%d",&tt);
    61     while(tt--)
    62     {
    63         read();
    64         go();
    65     }
    66     system("pause");
    67     return 0;
    68 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    2019-3-24
    模板
    试试Markdown编辑器
    Codeforces Round #529 (Div. 3) D. Circular Dance
    Codeforces Round #529 (Div. 3) C. Powers Of Two(数学????)
    poj 2566"Bound Found"(尺取法)
    poj 3273"Monthly Expense"(二分搜索+最小化最大值)
    二分搜索
    Codeforces Round #518 (Div. 2) B LCM
    2018.12.21 浪在ACM 集训队第十次测试赛
  • 原文地址:https://www.cnblogs.com/proverbs/p/2711151.html
Copyright © 2011-2022 走看看