zoukankan      html  css  js  c++  java
  • 洛谷P4486 Kakuro

    题意:你有一个棋盘,某些格子是限制条件,形如"从这里开始下面所有连续空格的和为a"或"从这里开始向右的所有连续空格之和为b"一个格子可以同时拥有两个限制条件。

    每个数都必须是正整数。

    现在你可以把某些格子加/减1,并花费相应的代价。可以操作无数次。求把棋盘变得合法的最小代价。

    解:没想出来,看了题解......

    一开始想了数字和条件构成二分图,又想了行列连边,但是始终建不出图来。

    行列连边。

    因为既可以加又可以减不好搞,我们可以先全部转换成满足条件的最小值,然后往上加。

    从最小值到初始值的时候,边权为负。之后边权为正。

    不可修改的地方边权为INF。

    然后跑一个最小费用可行流就是答案。

    如何判断无解?

    考虑每条边,如果有的边费用为INF但是有流量,就不合法。

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <queue>
      4 #include <cstring>
      5 
      6 typedef long long LL;
      7 const LL N = 2000, M = 1000010, INF = 0x3f3f3f3f, J = 35;
      8 
      9 struct Edge {
     10     LL nex, v, c, len;
     11 }edge[N << 1]; LL top = 1;
     12 
     13 LL e[N], d[N], vis[N], pre[N], flow[N];
     14 std::queue<LL> Q;
     15 LL fr[J][J], val[J][J], v2[J][J], cst[J][J], c2[J][J], m;
     16 
     17 inline void add(LL x, LL y, LL z, LL w) {
     18     top++;
     19     edge[top].v = y;
     20     edge[top].c = z;
     21     edge[top].len = w;
     22     edge[top].nex = e[x];
     23     e[x] = top;
     24 
     25     top++;
     26     edge[top].v = x;
     27     edge[top].c = 0;
     28     edge[top].len = -w;
     29     edge[top].nex = e[y];
     30     e[y] = top;
     31     return;
     32 }
     33 
     34 inline bool SPFA(LL s, LL t) {
     35     memset(d, 0x3f, sizeof(d));
     36     d[s] = 0;
     37     flow[s] = INF;
     38     vis[s] = 1;
     39     Q.push(s);
     40     while(!Q.empty()) {
     41         LL x = Q.front();
     42         Q.pop();
     43         vis[x] = 0;
     44         for(LL i = e[x]; i; i = edge[i].nex) {
     45             LL y = edge[i].v;
     46             if(edge[i].c && d[y] > d[x] + edge[i].len) {
     47                 d[y] = d[x] + edge[i].len;
     48                 pre[y] = i;
     49                 flow[y] = std::min(flow[x], edge[i].c);
     50                 if(!vis[y]) {
     51                     vis[y] = 1;
     52                     Q.push(y);
     53                 }
     54             }
     55         }
     56     }
     57     return d[t] < INF;
     58 }
     59 
     60 inline void update(LL s, LL t) {
     61     LL temp = flow[t];
     62     while(t != s) {
     63         LL i = pre[t];
     64         edge[i].c -= temp;
     65         edge[i ^ 1].c += temp;
     66         t = edge[i ^ 1].v;
     67     }
     68     return;
     69 }
     70 
     71 inline LL solve(LL s, LL t, LL &cost) {
     72     LL ans = 0;
     73     cost = 0;
     74     while(SPFA(s, t)) {
     75         if(d[t] > 0) {
     76             break;
     77         }
     78         ans += flow[t];
     79         cost += flow[t] * d[t];
     80         update(s, t);
     81     }
     82     return ans;
     83 }
     84 
     85 inline LL id(LL x, LL y) {
     86     return (x - 1) * m + y;
     87 }
     88 
     89 int main() {
     90     LL n, use = 0;
     91     scanf("%lld%lld", &n, &m);
     92     for(LL i = 1; i <= n; i++) {
     93         for(LL j = 1; j <= m; j++) {
     94             scanf("%lld", &fr[i][j]);
     95         }
     96     }
     97     for(LL i = 1; i <= n; i++) {
     98         for(LL j = 1; j <= m; j++) {
     99             if(fr[i][j] == 0) {
    100                 continue;
    101             }
    102             else if(fr[i][j] == 1) {
    103                 scanf("%lld", &val[i][j]);
    104             }
    105             else if(fr[i][j] == 2) {
    106                 scanf("%lld", &v2[i][j]);
    107             }
    108             else if(fr[i][j] == 3) {
    109                 scanf("%lld%lld", &val[i][j], &v2[i][j]);
    110             }
    111             else {
    112                 scanf("%lld", &val[i][j]);
    113             }
    114         }
    115     }
    116     for(LL i = 1; i <= n; i++) {
    117         for(LL j = 1; j <= n; j++) {
    118             if(fr[i][j] == 0) {
    119                 continue;
    120             }
    121             else if(fr[i][j] == 1) {
    122                 scanf("%lld", &cst[i][j]);
    123             }
    124             else if(fr[i][j] == 2) {
    125                 scanf("%lld", &c2[i][j]);
    126             }
    127             else if(fr[i][j] == 3) {
    128                 scanf("%lld%lld", &cst[i][j], &c2[i][j]);
    129             }
    130             else {
    131                 scanf("%lld", &cst[i][j]);
    132             }
    133             if(cst[i][j] == -1) {
    134                 cst[i][j] = INF;
    135             }
    136             if(c2[i][j] == -1) {
    137                 c2[i][j] = INF;
    138             }
    139         }
    140     }
    141     // read over
    142     LL lm = n * m;
    143     LL s = lm * 2 + 1;
    144     LL t = s + 1;
    145     for(LL i = 1; i <= n; i++) {
    146         for(LL j = 1; j <= m; j++) {
    147             if(fr[i][j] == 0) {
    148                 continue;
    149             }
    150             if(fr[i][j] == 1 || fr[i][j] == 3) {
    151                 // id(i, j)
    152                 LL cnt = 0;
    153                 for(LL k = i + 1; k <= n; k++) {
    154                     if(fr[k][j] == 4) {
    155                         cnt++;
    156                     }
    157                     else {
    158                         break;
    159                     }
    160                 }
    161                 // val[i][j] - cnt
    162                 if(val[i][j] > cnt) {
    163                     add(s, id(i, j), val[i][j] - cnt, -cst[i][j]);
    164                 }
    165                 add(s, id(i, j), INF, cst[i][j]);
    166                 use += cst[i][j] * abs(val[i][j] - cnt);
    167             }
    168             if(fr[i][j] == 2 || fr[i][j] == 3) {
    169                 LL cnt = 0;
    170                 for(LL k = j + 1; k <= m; k++) {
    171                     if(fr[i][k] == 4) {
    172                         cnt++;
    173                     }
    174                     else {
    175                         break;
    176                     }
    177                 }
    178                 if(v2[i][j] > cnt) {
    179                     add(id(i, j) + lm, t, v2[i][j] - cnt, -c2[i][j]);
    180                 }
    181                 add(id(i, j) + lm, t, INF, c2[i][j]);
    182                 use += c2[i][j] * abs(v2[i][j] - cnt);
    183             }
    184             if(fr[i][j] == 4) {
    185                 LL a, b;
    186                 for(LL k = i - 1; k >= 1; k--) {
    187                     if(fr[k][j] == 1 || fr[k][j] == 3) {
    188                         a = id(k, j);
    189                         break;
    190                     }
    191                 }
    192                 for(LL k = j - 1; k >= 1; k--) {
    193                     if(fr[i][k] == 2 || fr[i][k] == 3) {
    194                         b = id(i, k) + lm;
    195                         break;
    196                     }
    197                 }
    198                 if(val[i][j] > 1) {
    199                     add(a, b, val[i][j] - 1, -cst[i][j]);
    200                 }
    201                 add(a, b, INF, cst[i][j]);
    202                 use += cst[i][j] * abs(val[i][j] - 1);
    203             }
    204         }
    205     }
    206 
    207     LL ans;
    208     solve(s, t, ans);
    209     ans += use;
    210 
    211     /*if(ans >= INF) {
    212         puts("-1");
    213         return 0;
    214     }*/
    215     for(int i = 2; i <= top; i += 2) {
    216         if(abs(edge[i].len) == INF && (edge[i].c && edge[i ^ 1].c)) {
    217             puts("-1");
    218             return 0;
    219         }
    220     }
    221 
    222     printf("%lld", ans);
    223     return 0;
    224 }
    AC代码

    思考:能否不转换为最小?好像无法判断是否合法...

  • 相关阅读:
    c++类的大小
    c++面向对象的程序设计
    c++拷贝控制
    vsftpd出现“Response: 500 OOPS: cannot change directory”解决方法(转载)
    CentOS 安装 MRTG 软件完成后的 403 Forbidden(转载)
    Linux服务器 /var/spool/clientmqueue 目录下产生大量文件的删除办法
    mysql修改端口经验
    yum install mysql(转载)
    yum install tomcat
    yun install java
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10105509.html
Copyright © 2011-2022 走看看