• HDU 3338 Kakuro Extension


    Kakuro Extension

    题意:现在有一个n*m的矩形,现在每个白色的点都可以填 [1, 9] 中的一个数字。现在要求每行加起来的值等于左边的那个黑块的右值,每列加起来等于上边那个黑块的左值,求合法方案数。

    题解:因为每个点至少是1,如果直接建边跑最大流的话会导致某些点的值为0,现在要保证每个点至少为1,我们可以直接把 s 流向每个白点流量为1, 然后黑点流入白点的流量减少边数的流量,最后跑最大流,输出答案。

    代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
      4 #define LL long long
      5 #define ULL unsigned LL
      6 #define fi first
      7 #define se second
      8 #define pb emplace_back
      9 #define lson l,m,rt<<1
     10 #define rson m+1,r,rt<<1|1
     11 #define lch(x) tr[x].son[0]
     12 #define rch(x) tr[x].son[1]
     13 #define max3(a,b,c) max(a,max(b,c))
     14 #define min3(a,b,c) min(a,min(b,c))
     15 typedef pair<int,int> pll;
     16 const int inf = 0x3f3f3f3f;
     17 const LL INF = 0x3f3f3f3f3f3f3f3f;
     18 const LL mod =  (int)1e9+7;
     19 const int N = 100*101 * 2;
     20 const int M = N * 20;
     21 int ans[150][150];
     22 int val[150][150][2];
     23 int head[N], deep[N], cur[N];
     24 int w[M], to[M], nx[M];
     25 int tot;
     26 void add(int u, int v, int val){
     27     w[tot]  = val; to[tot] = v;
     28     nx[tot] = head[u]; head[u] = tot++;
     29 
     30     w[tot] = 0; to[tot] = u;
     31     nx[tot] = head[v]; head[v] = tot++;
     32 }
     33 int bfs(int s, int t){
     34     queue<int> q;
     35     memset(deep, 0, sizeof(deep));
     36     q.push(s);
     37     deep[s] = 1;
     38     while(!q.empty()){
     39         int u = q.front();
     40         q.pop();
     41         for(int i = head[u]; ~i; i = nx[i]){
     42             if(w[i] > 0 && deep[to[i]] == 0){
     43                 deep[to[i]] = deep[u] + 1;
     44                 q.push(to[i]);
     45             }
     46         }
     47     }
     48     return deep[t] > 0;
     49 }
     50 int Dfs(int u, int t, int flow){
     51     if(u == t) return flow;
     52     for(int &i = cur[u]; ~i; i = nx[i]){
     53         if(deep[u]+1 == deep[to[i]] && w[i] > 0){
     54             int di = Dfs(to[i], t, min(w[i], flow));
     55             if(di > 0){
     56                 w[i] -= di, w[i^1] += di;
     57                 return di;
     58             }
     59         }
     60     }
     61     return 0;
     62 }
     63 
     64 int Dinic(int s, int t){
     65     int ans = 0, tmp;
     66     while(bfs(s, t)){
     67         for(int i = 0; i <= t; i++) cur[i] = head[i];
     68         while(tmp = Dfs(s, t, inf)) ans += tmp;
     69     }
     70     return ans;
     71 }
     72 void init(){
     73     memset(head, -1, sizeof(head));
     74     tot = 0;
     75 }
     76 char str[N];
     77 int n, m;
     78 #define id(i,j) (i-1)*m+j
     79 void GG(){
     80     for(int i = 1; i <= n; i++)
     81         for(int j = 1; j <= m; j++){
     82             if(val[i][j][1] > 0){
     83                 for(int z = head[id(i,j)]; ~z; z = nx[z]){
     84                     if(z&1);
     85                     else {
     86                         int tx = to[z] / m + 1, ty = to[z] % m;
     87                         if(!ty) ty = m, tx -= 1;
     88                         ans[tx][ty] = 9 - w[z] + 1;
     89                     }
     90                 }
     91             }
     92         }
     93 }
     94 
     95 int main(){
     96     ///Fopen;
     97     while(~scanf("%d%d", &n, &m)){
     98        init(); for(int i = 1; i <= n; i++)
     99             for(int j = 1; j <= m; j++){
    100                 ans[i][j] = 0;
    101                 scanf("%s", str+1);
    102                 if(str[1] == '.') val[i][j][0] = val[i][j][1] = -2;
    103                 else {
    104                     if(str[1] == 'X') val[i][j][0] = -1; /// down
    105                     else val[i][j][0] = (str[1]-'0')*100 + (str[2]-'0')*10 + str[3] - '0';
    106                     if(str[5] == 'X') val[i][j][1] = -1;
    107                     else val[i][j][1] = (str[5]-'0')*100 + (str[6]-'0')*10 + str[7] - '0';
    108                 }
    109             }
    110         int s = 0, t = n*m*2+1;
    111         for(int i = 1; i <= n; i++){
    112             for(int j = 1; j <= m; j++){
    113                 if(val[i][j][1] > 0){
    114                     int tmp = val[i][j][1];
    115                     int z = j+1;
    116                     while(z <= m && val[i][z][0] == -2){
    117                         add(id(i,j), id(i,z), 9);
    118                         add(s, id(i,z), 1);
    119                        // cout << i << ' ' << j << "  link   " << i << ' ' << z << endl;
    120                         z++;
    121                         tmp--;
    122                     }
    123                     add(s, id(i,j), tmp);
    124                     j = z - 1;
    125                 }
    126             }
    127         }
    128         for(int j = 1; j <= m; j++)
    129             for(int i = 1; i <= n; i++){
    130                 if(val[i][j][0] > 0){
    131                     int z = i + 1;
    132                     add(id(i,j)+n*m, t, val[i][j][0]);
    133                     while(z <= n && val[z][j][0] == -2){
    134                         add(id(z,j),id(i,j)+n*m,9);
    135                         z++;
    136                     }
    137                     i = z - 1;
    138                 }
    139         }
    140         //puts("Oh mather fuck!!!");
    141          int tt = Dinic(s,t);
    142          //cout << tt << endl;
    143         GG();
    144         for(int i = 1; i <= n; i++){
    145             for(int j = 1; j <= m; j++){
    146                 if(ans[i][j]) printf("%d", ans[i][j]);
    147                 else printf("_");
    148                 if(j!=m) printf(" ");
    149             }
    150             puts("");
    151         }
    152     }
    153     return 0;
    154 }
    155 /*
    156 2 2
    157 XXXXXXX 009/XXX
    158 XXX/009 .......
    159 */
    View Code
  • 相关阅读:
    《构建之法》阅读笔记二
    《构建之法》阅读笔记一
    软件工程个人课程总结
    纯随机数生成器
    递归方法
    素数的输出
    字母统计|英语的26 个字母在一本小说中是如何分布的
    类的声明
    FileInputStream类与FileOutputStream类
    验证码|程序登录界面
  • 原文地址:https://www.cnblogs.com/MingSD/p/9738766.html
Copyright © 2020-2023  润新知