zoukankan      html  css  js  c++  java
  • Matrix Again HDU

    Practice link:  https://vjudge.net/problem/HDU-3376

    题意:给你一个 n*n 的矩阵,每个点有自身的权值,从左上角向右下角走只能向右或向下,从右下角向左上角走只能向左或向上,问你从左上角走向右下角再从右下角走向左上角且每个点只能走一次,问你最大权值之和是多少。

    思路:首先从右下角到左上角的过程可以转化为从左上角到右下角,那么问题就变成了从左上角到右下角的两条没有重复点的路径的最大权值和。然后看到是走矩阵且要求权值之和最大且每个格子只能走一次,就想到最大费用最大流。首先建立超级源点和超级汇点,源点到左上角的点的流量为2,费用为 0,右下角的点到汇点的流量为 2 ,费用为 0,由于每个点只能走一次,那么我们就进行拆点,即把点 k 拆成两个点 k1 和 k2,这两个点之间的流量为 1 ,费用为点 k 的权值(除了左上角和右下角的两个点的流量需要为 2)。其余可以联通的点之间的流量为 1 ,费用为 0 即可。

             最后跑一遍最大费用最大流,又因为左上角和右下角的点经过了两次,最后答案要减去这两个点的权值。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<iostream>
      5 #include<string>
      6 #include<vector>
      7 #include<stack>
      8 #include<bitset>
      9 #include<cstdlib>
     10 #include<cmath>
     11 #include<set>
     12 #include<list>
     13 #include<deque>
     14 #include<map>
     15 #include<queue>
     16 #define ll long long
     17 #define MOD 998244353
     18 #define INF 0x3f3f3f3f
     19 #define mem(a,x) memset(a,x,sizeof(a))
     20 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
     21 using namespace std;
     22 
     23 const int maxn = 800000;
     24 
     25 bool vis[maxn];
     26 int n,m,s,t;
     27 int dis[maxn],pre[maxn],last[maxn],flow[maxn],maxflow,maxcost;
     28 
     29 struct node{
     30     int to,nxt,flow,dis;  //flow流量 dis花费
     31 }edge[4*maxn];
     32 int head[4*maxn],cnt=0;
     33 
     34 void addl(int u,int v,int flow,int dis)
     35 {
     36     edge[cnt].to=v;
     37     edge[cnt].flow=flow;
     38     edge[cnt].dis=dis;
     39     edge[cnt].nxt=head[u];
     40     head[u]=cnt++;
     41 }
     42 
     43 bool spfa(int s,int t)
     44 {
     45     for(int i=0;i<=2*n*n+1;i++){
     46         dis[i]=-1;
     47         flow[i]=INF;
     48         vis[i]=0;
     49     }
     50     queue<int>q;
     51     q.push(s);
     52     vis[s]=1;
     53     dis[s]=0;
     54     pre[t]=-1;
     55     while(!q.empty()){
     56         int now=q.front();
     57         q.pop();
     58         vis[now]=0;
     59         for(int i=head[now];i!=-1;i=edge[i].nxt)
     60         {
     61             if(edge[i].flow>0&&dis[edge[i].to]<dis[now]+edge[i].dis)
     62             {
     63                 dis[edge[i].to]=dis[now]+edge[i].dis;
     64                 pre[edge[i].to]=now;
     65                 last[edge[i].to]=i;
     66                 flow[edge[i].to]=min(flow[now],edge[i].flow);
     67                 if(!vis[edge[i].to])
     68                 {
     69                     vis[edge[i].to]=1;
     70                     q.push(edge[i].to);
     71                 }
     72             }
     73         }
     74     }
     75     return pre[t]!=-1;
     76 }
     77 void MCMF()
     78 {
     79     while(spfa(s,t))
     80     {
     81         int now=t;
     82         maxflow+=flow[t];
     83         maxcost+=flow[t]*dis[t];
     84         while(now!=s)
     85         {
     86             edge[last[now]].flow-=flow[t];
     87             edge[last[now]^1].flow+=flow[t];
     88             now=pre[now];
     89         }
     90     }
     91 }
     92 int mp[605][605];
     93 int main()
     94 {
     95     while (scanf("%d",&n)!=EOF) {
     96         mem(head,-1);
     97         mem(pre,-1);
     98         cnt=0;
     99         maxflow=0;
    100         maxcost=0;
    101         s=0;
    102         t=2*n*n+1;
    103         addl(s,1,2,0);
    104         addl(1,s,0,0);
    105         for(int i=1;i<=n;i++){
    106             for(int j=1;j<=n;j++){
    107                 scanf("%d",&mp[i][j]);
    108                 int num=(i-1)*n+j;
    109                 if(i==j&&(num==1||num==n*n)){
    110                     addl(num,num+n*n,2,mp[i][j]);
    111                     addl(num+n*n,num,0,-mp[i][j]);
    112                 }else{
    113                     addl(num+n*n,num,0,-mp[i][j]);
    114                     addl(num,num+n*n,1,mp[i][j]);
    115                 }
    116                 if(i+1<=n){
    117                     addl(num+n*n,i*n+j,1,0);
    118                     addl(i*n+j,num+n*n,0,0);
    119                 }
    120                 if(j+1<=n){
    121                     addl(num+n*n,num+1,1,0);
    122                     addl(num+1,num+n*n,0,0);
    123                 }
    124             }
    125         }
    126         addl(2*n*n,t,2,0);
    127         addl(t,2*n*n,0,0);
    128         MCMF();
    129         printf("%d
    ",maxcost-mp[1][1]-mp[n][n]);
    130     }
    131     return 0;
    132 }
    越自律,越自由
  • 相关阅读:
    LeetCode 876——链表的中间结点
    LeetCode 206——反转链表
    一次漫长的代码复现经历
    在 C/C++ 中使用 TensorFlow 预训练好的模型—— 直接调用 C++ 接口实现
    编译 TensorFlow 的 C/C++ 接口
    TensorFlow 同时调用多个预训练好的模型
    在 C/C++ 中使用 TensorFlow 预训练好的模型—— 间接调用 Python 实现
    TensorFlow 调用预训练好的模型—— Python 实现
    Python 学习笔记之 Numpy 库——文件操作
    Python 学习笔记之 Numpy 库——数组基础
  • 原文地址:https://www.cnblogs.com/ha-chuochuo/p/13543664.html
Copyright © 2011-2022 走看看