• HDU 4862 Jump (2014-多校1-1002,最小K路径覆盖,最小费用最大流)


    题目:

    http://acm.hdu.edu.cn/showproblem.php?pid=4862

    题意:

    给你一个n*m的矩阵,填充着0-9的数字,每次能从一个点出发,到它的右边或者下边的点,花费为|x1-x2|+|y1-y2|-1,如果跳跃的起点和终点的数字相同,则获得这个数字的收益,不能走已经走过的点

    有K次重新选择起点的机会

    如果可以走遍所有点,则输出最大的价值(收益-花费)

    否则,输出-1

    方法:

    最小K路径覆盖,最小费用最大流

    建图:

    每个点拆为2点:X部和Y部,(a,b)表示流量a,费用b

    源点与X部每个点连(1,0)的边

    Y部每个点与汇点连(1,0)的边

    X部的点如果可以到Y部的点,则连(1,花费-收益)的边

    源点与一个新点连(k,0)的边,新点与Y部每个点连(1,0)的边

    结果:

    如果满流,则输出0-费用

    否则,输出-1

    代码:

      1 // #pragma comment(linker, "/STACK:102400000,102400000")
      2 #include <cstdio>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <string>
      6 #include <cmath>
      7 #include <set>
      8 #include <list>
      9 #include <map>
     10 #include <iterator>
     11 #include <cstdlib>
     12 #include <vector>
     13 #include <queue>
     14 #include <stack>
     15 #include <algorithm>
     16 #include <functional>
     17 using namespace std;
     18 typedef long long LL;
     19 #define ROUND(x) round(x)
     20 #define FLOOR(x) floor(x)
     21 #define CEIL(x) ceil(x)
     22 // const int maxn = 210;
     23 // const int maxm = 200010;
     24 // const int inf = 0x3f3f3f3f;
     25 const LL inf64 = 0x3f3f3f3f3f3f3f3fLL;
     26 const double INF = 1e30;
     27 const double eps = 1e-6;
     28 const int P[4] = {0, 0, -1, 1};
     29 const int Q[4] = {1, -1, 0, 0};
     30 const int PP[8] = { -1, -1, -1, 0, 0, 1, 1, 1};
     31 const int QQ[8] = { -1, 0, 1, -1, 1, -1, 0, 1};
     32 
     33 /**
     34 *最小(大)费用最大流:SPFA增广路($O(w*O(SPFA))$)
     35 *最大费用:费用取反addEdge(,,,-cost);
     36 *输入:图(链式前向星),n(顶点个数,包含源汇),s(源),t(汇)
     37 *输出:minCostMaxflow(int s, int t, int &cost)返回流量, cost为费用
     38 *打印路径方法:按反向边(i&1)的flow 找,或者按边的flow找
     39 */
     40 const int maxn = 210;
     41 const int maxm = 200010;
     42 const int inf = 0x3f3f3f3f;
     43 struct Edge
     44 {
     45     int u, v;
     46     int cap, flow;
     47     int cost;
     48     int next;
     49 } edge[maxm];
     50 int head[maxn], en; //需初始化
     51 int n, m;
     52 int st, ed;
     53 bool vis[maxn];
     54 int pre[maxn], dis[maxn];
     55 void addse(int u, int v, int cap, int flow, int cost)
     56 {
     57     edge[en].u = u;
     58     edge[en].v = v;
     59     edge[en].cap = cap;
     60     edge[en].flow = flow;
     61     edge[en].cost = cost;
     62     edge[en].next = head[u];
     63     head[u] = en++;
     64 }
     65 void adde(int u, int v, int cap, int cost)
     66 {
     67     addse(u, v, cap, 0, cost);
     68     addse(v, u, 0, 0, -cost); //注意加反向0 边
     69 }
     70 bool spfa(int s, int t)
     71 {
     72     queue<int>q;
     73     for (int i = 0; i < n; i++)
     74     {
     75         dis[i] = inf;
     76         vis[i] = false;
     77         pre[i] = -1;
     78     }
     79     dis[s] = 0;
     80     vis[s] = true;
     81     q.push(s);
     82     while (!q.empty())
     83     {
     84         int u = q.front();
     85         q.pop();
     86         vis[u] = false;
     87         for (int i = head[u]; i != -1; i = edge[i].next)
     88         {
     89             int v = edge[i].v;
     90             if (edge[i].cap > edge[i].flow &&
     91                     dis[v] > dis[u] + edge[i].cost )
     92             {
     93                 dis[v] = dis[u] + edge[i].cost;
     94                 pre[v] = i;
     95                 if (!vis[v])
     96                 {
     97                     vis[v] = true;
     98                     q.push(v);
     99                 }
    100             }
    101         }
    102     }
    103     if (pre[t] == -1)return false;
    104     else return true;
    105 }
    106 int minCostMaxflow(int s, int t, int &cost)//返回流量, cost为费用
    107 {
    108     int flow = 0;
    109     cost = 0;
    110     while (spfa(s, t))
    111     {
    112         int Min = inf;
    113         for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].v])
    114         {
    115             if (Min > edge[i].cap - edge[i].flow)
    116                 Min = edge[i].cap - edge[i].flow;
    117         }
    118         for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].v])
    119         {
    120             edge[i].flow += Min;
    121             edge[i ^ 1].flow -= Min;
    122             cost += edge[i].cost * Min;
    123         }
    124         flow += Min;
    125     }
    126     return flow;
    127 }
    128 int N, M, K;
    129 int kase;
    130 int mtx[maxn][maxn];
    131 int disxy(int x1, int y1, int x2, int y2)
    132 {
    133     return abs(x1 - x2) + abs(y1 - y2) - 1;
    134 }
    135 void build()
    136 {
    137     n = 3 + N * M * 2;
    138     st = 0, ed = 1;
    139     for (int i = 0; i < N; i++)
    140     {
    141         for (int j = 0; j < M; j++)
    142         {
    143             adde(st, i * M + j + 3, 1, 0);
    144         }
    145     }
    146     adde(st, 2, K, 0);
    147     for (int i = 0; i < N; i++)
    148     {
    149         for (int j = 0; j < M; j++)
    150         {
    151             adde(2, i * M + j + N * M + 3, 1, 0);
    152             adde(i * M + j + N * M + 3, ed, 1, 0);
    153         }
    154     }
    155     for (int i = 0; i < N; i++)
    156     {
    157         for (int j = 0; j < M; j++)
    158         {
    159             for (int h = i + 1; h < N; h++)
    160             {
    161                 if (mtx[i][j] == mtx[h][j])
    162                 {
    163                     adde(i * M + j + 3, h * M + j + N * M + 3, 1, h - i - 1 - mtx[i][j]);
    164                     // cout << i << " " << j << " " << h << " " << j << endl;
    165                 }
    166                 else
    167                 {
    168                     adde(i * M + j + 3, h * M + j + N * M + 3, 1, h - i - 1);
    169                 }
    170             }
    171             for (int h = j + 1; h < M; h++)
    172             {
    173                 if (mtx[i][j] == mtx[i][h])
    174                 {
    175                     adde(i * M + j + 3, i * M + h + N * M + 3, 1, h - j - 1 - mtx[i][j]);
    176                     // cout << i << " " << j << " " << i << " " << h << endl;
    177                 }
    178                 else
    179                 {
    180                     adde(i * M + j + 3, i * M + h + N * M + 3, 1, h - j - 1);
    181                 }
    182             }
    183         }
    184     }
    185 }
    186 void init()
    187 {
    188     memset(head, -1, sizeof(head));
    189     en = 0;
    190     kase++;
    191 }
    192 void input()
    193 {
    194     scanf("%d%d%d", &N, &M, &K);
    195     for (int i = 0; i < N; i++)
    196     {
    197         char str[maxn];
    198         scanf("%s", str);
    199         for (int j = 0; j < M; j++)
    200         {
    201             mtx[i][j] = str[j] - '0';
    202         }
    203     }
    204 }
    205 void debug()
    206 {
    207     //
    208 }
    209 void solve()
    210 {
    211     build();
    212     int cost;
    213     int flow = minCostMaxflow(st, ed, cost);
    214     // cout << "flow,cost: " << flow << " " << cost << endl;
    215     if (flow == N * M)
    216     {
    217         printf("Case %d : %d
    ", kase, -cost);
    218     }
    219     else
    220     {
    221         printf("Case %d : %d
    ", kase, -1);
    222     }
    223 }
    224 void output()
    225 {
    226     //
    227 }
    228 int main()
    229 {
    230     // int size = 256 << 20; // 256MB
    231     // char *p = (char *)malloc(size) + size;
    232     // __asm__("movl %0, %%esp
    " :: "r"(p));
    233 
    234     // std::ios_base::sync_with_stdio(false);
    235 #ifndef ONLINE_JUDGE
    236     freopen("in.cpp", "r", stdin);
    237 #endif
    238 
    239     kase = 0;
    240     int T;
    241     scanf("%d", &T);
    242     while (T--)
    243     {
    244         init();
    245         input();
    246         solve();
    247         output();
    248     }
    249     return 0;
    250 }
    HDU 4862
  • 相关阅读:
    结对编程2
    结对编程总结:简单的四则运算生成程序
    我的结对项目心得与代码规范
    一个团队和他们的调查表-----("调查表与调查结果分析"心得体会)
    目标?我定好了!(我的软件工程课目标)
    Jmeter响应数据为乱码的处理
    软件工程课程建议
    结对编程之Fault、Error、Failure
    我的结对项目编程感想
    调查问卷后的心得
  • 原文地址:https://www.cnblogs.com/xysmlx/p/3878836.html
Copyright © 2020-2023  润新知