zoukankan      html  css  js  c++  java
  • HDU 4862 Jump 费用流

    又是一个看了题解以后还坑了一天的题…… 结果最后发现是抄代码的时候少写了一个负号。

    题意:

      有一个n*m的网格,其中每个格子上都有0~9的数字。现在你可以玩K次游戏。

      一次游戏是这样定义的: 你可以选任意之前没有走过的格子作为起点。然后走任意步,其中每一步你可以向右或者向下走任意格。假如从(x1, y1)走到(x2, y2)需要花费能量|x1-x2|+|y1-y2|-1,如果这一步和上一步格子的数字相同,那么可以获得格子上相应数字的能量。能量可以为负值。

      问你,在K次以内走完所以格子最多能得到多少能量,若走不完,输出-1 。

    思路:(直接抄题解)

      最小K路径覆盖的模型,用费用流或者KM算法解决,构造二部图,X部有N*M个节点,源点向X部每个节点连一条边,流量1,费用0Y部有N*M个节点,每个节点向汇点连一条边,流量1,费用0,如果X部的节点x可以在一步之内到达Y部的节点y,那么就连边x->y,费用为从x格子到y格子的花费能量减去得到的能量,流量1,再在X部增加一个新的节点,表示可以从任意节点出发K次,源点向其连边,费用0,流量K,这个点向Y部每个点连边,费用0,流量1,最这个图跑最小费用最大流,如果满流就是存在解,反之不存在,最小费用的相反数就是可以获得的最大能量。

    代码:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <cmath>
      6 #include <algorithm>
      7 #include <string>
      8 #include <queue>
      9 #include <stack>
     10 #include <vector>
     11 #include <map>
     12 #include <set>
     13 #include <functional>
     14 #include <time.h>
     15 
     16 using namespace std;
     17 
     18 const int INF = 1<<29;
     19 const int MAXN = 2050;
     20 
     21 struct Edge {
     22     int from, to, cap, flow, cost;
     23     Edge(int from, int to, int cap, int flow, int cost)
     24     : from(from), to(to), cap(cap), flow(flow), cost(cost) {}
     25 };
     26 
     27 struct MCMF {
     28     int n, m, s, t;
     29     vector<Edge> edges;
     30     vector<int> G[MAXN];
     31 
     32     int inq[MAXN];
     33     int d[MAXN];
     34     int p[MAXN];
     35     int a[MAXN];
     36     int cnt[MAXN];
     37 
     38     void init(int n) {
     39         this->n = n;
     40         for (int i = 0; i < n; i++) G[i].clear();
     41         edges.clear();
     42     }
     43 
     44     void addEdge(int from, int to, int cap, int cost) {
     45         edges.push_back(Edge(from, to, cap, 0, cost));
     46         edges.push_back(Edge(to, from, 0, 0, -cost));
     47         m = edges.size();
     48         G[from].push_back(m-2);
     49         G[to].push_back(m-1);
     50     }
     51 
     52     bool BellmanFord(int s, int t, int &flow, int &cost) {
     53         for (int i = 0; i < n; i++) d[i] = INF;
     54         memset(inq, 0, sizeof(inq));
     55         memset(cnt, 0, sizeof(cnt));
     56         d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;
     57 bool flag = false;
     58         queue<int> Q;
     59         Q.push(s);
     60         while (!Q.empty()) {
     61             int u = Q.front(); Q.pop();
     62 //printf("u: %d %d
    ", u, Q.size());
     63             inq[u] = 0;
     64             for (int i = 0; i < G[u].size(); i++) {
     65                 Edge &e = edges[G[u][i]];
     66                 if (e.cap>e.flow && d[e.to] > d[u]+e.cost) {
     67                     cnt[e.to] = cnt[u]+1;
     68                     if (cnt[e.to]>=n) {flag = true; break; }
     69 //printf("u: %d v: %d
     d[u]: %d d[v]: %d cost: %d
    cap: %d flow: %d
    ", u, e.to, d[u], d[e.to], e.cost, e.cap, e.flow);
     70                     d[e.to] = d[u] + e.cost;
     71                     p[e.to] = G[u][i];
     72                     a[e.to] = min(a[u], e.cap-e.flow);
     73                     if (!inq[e.to]) { Q.push(e.to); inq[e.to] = 1; }
     74                 }
     75             }
     76             if (flag)break;
     77         }
     78         if (d[t]==INF) return false;
     79         flow += a[t];
     80         cost += d[t]*a[t];
     81         int u = t;
     82         while (u!=s) {
     83             edges[p[u]].flow += a[t];
     84             edges[p[u]^1].flow -= a[t];
     85             u = edges[p[u]].from;
     86         }
     87         return true;
     88     }
     89 
     90     pair<int, int> MinCost(int s, int t) {
     91         int flow = 0, cost = 0;
     92         while (BellmanFord(s, t, flow, cost)) ;
     93         return make_pair(flow, cost);
     94     }
     95     void print(){
     96         for(int i=0;i<n;i++){
     97             printf("%d :",i);
     98             for(int j=0;j<G[i].size();j++)
     99                 printf("(%d %d %d)",edges[G[i][j]].to,edges[G[i][j]].cap,edges[G[i][j]].cost);
    100             puts("");
    101         }
    102     }
    103 }solver;
    104 
    105 int N, M, K;
    106 int grid[15][105];
    107 
    108 void solve() {
    109     char tmp[200];
    110     scanf("%d%d%d", &N, &M, &K);
    111     for (int i = 0; i < N; i++) {
    112         scanf("%s", tmp);
    113         for (int j = 0; j < M; j++) {
    114             grid[i][j] = tmp[j] - '0';
    115         }
    116     }
    117     int num = N*M; //总的格点数
    118     //格点的编号规则: grid[i][j] = i*M + j
    119 
    120     //建图:
    121     //编号规则:
    122     /*
    123     0~num : 每个点的第一部分
    124     num~2*num-1 : 每个点的第二部分
    125     2*num: 原点
    126     2*num+1 : 额外点
    127     2*num+2 :
    128     */
    129     int st = 2*num, ad = st+1, ed = ad+1;
    130     solver.init(2*num+3);
    131     for (int i = 0; i < num; i++) { //原点到第一部分的每个点有一条容量为1,费用为0的边
    132         solver.addEdge(st, i, 1, 0);
    133     }
    134     for (int i = num; i < 2*num; i++) { //每个点的第二部分到汇点有一个容量为1,费用为0
    135         solver.addEdge(i, ed, 1, 0);
    136     }
    137     solver.addEdge(st, ad, K, 0);
    138     for (int i = num; i < 2*num; i++) { //额外点到每个点的第二部分的边
    139         solver.addEdge(ad, i, 1, 0);
    140     }
    141     for (int i = 0; i < N; i++)
    142         for  (int j = 0; j < M; j++) { //对于每一个点
    143             for (int x = i+1; x < N; x++) {
    144                 int cost = x-i-1;
    145                 if (grid[i][j]==grid[x][j])
    146                     cost -= grid[i][j];
    147                 solver.addEdge(i*M+j, num+x*M+j, 1, cost);
    148             }
    149 
    150             for (int y = j+1; y < M; y++) {
    151                 int cost = y-j-1;
    152                 if (grid[i][j]==grid[i][y])
    153                     cost -= grid[i][j];
    154                 solver.addEdge(i*M+j, num+i*M+y, 1, cost);
    155             }
    156         }
    157 //puts("ok");
    158 //solver.print();
    159 
    160     pair<int, int> ans = solver.MinCost(st, ed);
    161     if (ans.first==num)
    162         printf("%d
    ", -ans.second);
    163     else
    164         puts("-1");
    165 }
    166 
    167 int main() {
    168     #ifdef Phantom01
    169         freopen("HDU4862.txt", "r", stdin);
    170     #endif //Phantom01
    171 
    172     int Case;
    173     scanf("%d", &Case);
    174     for (int i = 1; i <= Case; i++) {
    175         printf("Case %d : ", i);
    176         solve();
    177     }
    178 
    179     return 0;
    180 }
    HDU4862

      

  • 相关阅读:
    生成测试报告unittest、HTMLTestRunner(pytest、allure)
    接口自动化上传视频(python)
    Android手机测试环境搭建
    jmeter性能测试监控
    jmeter多机联合负载
    jenkins+ant+jmeter接口自动化的持续集成
    jmeter+jenkins 配置过程(很详细)
    XSS攻击测试代码
    web安全测试之 xss攻击
    互联网公司--高级测试工程师面试经验分享
  • 原文地址:https://www.cnblogs.com/Phantom01/p/3864769.html
Copyright © 2011-2022 走看看