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 }
  • 相关阅读:
    Centos8.2安装Mongodb4.4.2(社区版)
    Spirng 循环依赖报错:Requested bean is currently in creation: Is there an unresolvable circular reference?
    SpringBoot Test 多线程报错:dataSource already closed
    SpringCloud Stream整合RabbitMQ3.5.0
    SpringBoot2.2.5整合ElasticSearch7.9.2
    ElasticSearch7.9.2设置密码
    CentOS7安装Kibana7.9.2
    张家界国庆6天行
    安装tomcat时,SYSTEM进程(PID=4)占用80端口的几种情况及解决方法(window7系统)
    竞品分析的目的是什么?如何筛选竞品?竞品分析资料来源?
  • 原文地址:https://www.cnblogs.com/GO-NO-1/p/3726322.html
Copyright © 2011-2022 走看看