zoukankan      html  css  js  c++  java
  • hdu 2686 Matrix && hdu 3367 Matrix Again (最大费用最大流)

    Matrix

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 1394    Accepted Submission(s): 758


    Problem Description
    Yifenfei very like play a number game in the n*n Matrix. A positive integer number is put in each area of the Matrix.
    Every time yifenfei should to do is that choose a detour which frome the top left point to the bottom right point and than back to the top left point with the maximal values of sum integers that area of Matrix yifenfei choose. But from the top to the bottom can only choose right and down, from the bottom to the top can only choose left and up. And yifenfei can not pass the same area of the Matrix except the start and end. 
     
    Input
    The input contains multiple test cases.
    Each case first line given the integer n (2<n<30) 
    Than n lines,each line include n positive integers.(<100)
     
    Output
    For each test case output the maximal values yifenfei can get.
     
    Sample Input
    2
    10 3
    5 10
    3
    10 3 3
    2 5 3
    6 7 10
    5
    1 2 3 4 5
    2 3 4 5 6
    3 4 5 6 7
    4 5 6 7 8
    5 6 7 8 9
     
    Sample Output
    28
    46
    80
     
    Author
    yifenfei
     
    Source
     
    Recommend
    yifenfei   |   We have carefully selected several similar problems for you:  3376 1533 3416 3081 2448 
     

    最大费用最大流,搞了好久= =!

    题意:

        给出一个n*n的矩阵,求(1,1)到(n,n)的两条不想交不重叠的路径,使经过的点的和最大。

    开始想到的是DP,后来发现了可以用多线程DP实现:

    参考:http://www.cnblogs.com/jackge/archive/2013/04/17/3025628.html

    让两个进程同时进行,枚举步数K,当x1==x2||y1==y2时跳过,得状态转移方程:

    dp(k, x1, y1, x2, y2) = max(dp(k-1, x1-1, y1, x2-1, y2), dp(k-1, x1-1, y1, x2, y2-1), dp(k-1, x1, y1-1, x2-1, y2), dp(k-1, x1, y1-1,x2, y2-1)) 

    + data(x1, y1) + data(x2, y2) ; 

    由于只能走右或下,所以坐标满足x+y=k。这样就能降低维数为3维,方程:

    dp(k, x1, x2) = max(dp(k-1, x1, x2), dp(k-1, x1-1, x2), dp(k-1, x1, x2-1), dp(k-1, x1-1, x2-1)) + data(x1, k-x1) + data(x2, k-x2) ;

    code:

     1 //31MS    1196K    880 B    G++
     2 #include<stdio.h>
     3 #include<string.h>
     4 #define N 50
     5 int p[N][N];
     6 int dp[2*N][N][N];
     7 int max(int a,int b)
     8 {
     9     return a>b?a:b;
    10 }
    11 int Max(int a,int b,int c,int d)
    12 {
    13     return max(a,max(b,max(c,d)));
    14 }
    15 int main(void)
    16 {
    17     int n;
    18     while(scanf("%d",&n)!=EOF)
    19     {
    20         memset(dp,0,sizeof(dp));
    21         for(int i=0;i<n;i++)
    22             for(int j=0;j<n;j++)
    23                 scanf("%d",&p[i][j]);
    24         for(int k=1;k<2*n-2;k++)
    25             for(int i=0;i<n;i++)
    26                 for(int j=0;j<n;j++){
    27                     if(i==j) continue;
    28                     dp[k][i][j]=Max(dp[k-1][i][j],dp[k-1][i-1][j],dp[k-1][i][j-1],dp[k-1][i-1][j-1]);
    29                     dp[k][i][j]+=p[i][k-i]+p[j][k-j];
    30                 }
    31         int ans=max(dp[2*n-3][n-1][n-2],dp[2*n-3][n-2][n-1])+p[0][0]+p[n-1][n-1];
    32         printf("%d
    ",ans);
    33     }
    34     return 0;
    35 }
    View Code

        先拆点构图,每个点一分为二,保证了只经过一次,其实网络流的方法就已经解决了这个问题,其次构图时注意把数变为负数,求最小费用最大流。

    其实构好图后就是直接套模板了,所以构图的时候注意点,处理一下(1,1)和(n,n)两个点,因为会经过两次。

    code:

      1 //31MS    384K    2396 B    G++
      2 #include<stdio.h>
      3 #include<string.h>
      4 #include<queue>
      5 #define N 2005
      6 #define inf 0x7ffffff
      7 using namespace std;
      8 struct node{
      9     int u,v,c,w;
     10     int next;
     11 }edge[10*N];
     12 int vis[N];
     13 int Head[N],d[N],edgenum;
     14 int pre[N],path[N];
     15 void addedge(int u,int v,int c,int w)
     16 {
     17     edge[edgenum].u=u;
     18     edge[edgenum].v=v;
     19     edge[edgenum].c=c;
     20     edge[edgenum].w=w;
     21     edge[edgenum].next=Head[u];
     22     Head[u]=edgenum++;
     23     
     24     edge[edgenum].u=v;
     25     edge[edgenum].v=u;
     26     edge[edgenum].c=0;
     27     edge[edgenum].w=-w;
     28     edge[edgenum].next=Head[v];
     29     Head[v]=edgenum++;
     30 }
     31 int SPFA(int s,int e)
     32 {
     33     memset(vis,0,sizeof(vis));
     34     memset(pre,-1,sizeof(pre));
     35     for(int i=0;i<=e;i++)
     36         d[i]=inf;
     37     queue<int>Q;
     38     d[s]=0;
     39     vis[s]=1;
     40     Q.push(s);
     41     while(!Q.empty()){
     42         int u=Q.front();
     43         Q.pop();
     44         vis[u]=0; //这里WA了好多次 
     45         for(int i=Head[u];i!=-1;i=edge[i].next){
     46             int v=edge[i].v;
     47             int w=edge[i].w;
     48             if(edge[i].c>0 && d[v]>d[u]+w){
     49                 pre[v]=u;
     50                 path[v]=i;
     51                 d[v]=d[u]+w;
     52                 if(!vis[v]){
     53                     vis[v]=1;
     54                     Q.push(v);
     55                 }
     56             }
     57         }
     58     }
     59     if(pre[e]!=-1) return 1;
     60     return 0;
     61 }
     62 int cost_min_flow(int s,int e)
     63 {
     64     int cost=0;
     65     while(SPFA(s,e)){
     66         int minc=inf;
     67         for(int i=e;i!=s;i=pre[i]){
     68             minc=minc<edge[path[i]].c?minc:edge[path[i]].c;
     69         }
     70         for(int i=e;i!=s;i=pre[i]){
     71             edge[path[i]].c-=minc;
     72             edge[path[i]^1].c+=minc;
     73             cost+=minc*edge[path[i]].w;
     74         }
     75     }
     76     return cost;
     77 }
     78 int main(void)
     79 {
     80     int n;
     81     int p[50][50];
     82     while(scanf("%d",&n)!=EOF)
     83     {
     84         edgenum=0;
     85         memset(Head,-1,sizeof(Head));
     86         int k=n*n;
     87         int s=0,e=2*k+1;
     88         for(int i=1;i<=n;i++)
     89             for(int j=1;j<=n;j++){
     90                 scanf("%d",&p[i][j]);
     91                 addedge(j+(i-1)*n,k+j+(i-1)*n,1,-p[i][j]);
     92                 if(j!=n) addedge(k+j+(i-1)*n,j+1+(i-1)*n,1,0);
     93                 if(i!=n) addedge(k+j+(i-1)*n,j+i*n,1,0);
     94             }
     95         addedge(s,1,2,0);
     96         addedge(1,k+1,1,0);
     97         addedge(2*k,e,2,0);
     98         addedge(k,2*k,1,0);
     99         printf("%d
    ",-cost_min_flow(s,e));
    100     }
    101     return 0;
    102 }
  • 相关阅读:
    easymock
    MySQL同时执行多条SQL语句解决办法
    MOP
    织梦dedecmsV5.7联动类型无法显示的处理方法
    如何查看sublime安装了哪些插件
    漏洞安全防范
    本地如何使用phpstudy环境搭建多站点
    Sublime 安装、插件CoolFormat
    CSharp设计模式读书笔记(2):工厂方法模式(学习难度:★★☆☆☆,使用频率:★★★★★)
    解决Unable to locate theme engine in module_path: "pixmap"
  • 原文地址:https://www.cnblogs.com/GO-NO-1/p/3726322.html
Copyright © 2011-2022 走看看