题意:

黑格子右上代表该行的和,左下代表该列下的和

链接:点我

这题可以用网络流做。以空白格为节点,假设流是从左流入,从上流出的,流入的容量为行和,流出来容量为列和,其余容量不变。求满足的最大流。由于流量有上下限限制,可以给每个数都减掉1,则填出来的数字范围为0—8, 就可以用单纯的网络流搞定了。求出来再加上就可以了。

这一题主要是在建图

建图:

一共有四类点:

1. 构造源点ST,汇点ED

2. 有行和的格子,即\上面有值的格子,此类节点设为A

3. 空白格,设为B

4. 有列和的格子,即\下面有值的格子,设为C

则可以建边:

1. ST------------A         容量:行和

2. A----------- B          容量:8

3. B------------C          容量:8

4. C------------ED          容量:列和

当然,反向边容量都置为0。

就是这么难~~

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. using namespace std;
  5.  
  6. #define INF 999999999
  7. #define MAXN 14000
  8. #define RE(x) (x)^1
  9.  
  10. int head[MAXN];
  11. int map[][];
  12. int st,ed;
  13. struct Edge
  14. {
  15. int v,next;
  16. int val;
  17. Edge(){}
  18. Edge( int V , int NEXT , int W = ):v(V),next(NEXT),val(W){}
  19. }edge[];
  20.  
  21. struct gg
  22. {
  23. int x,y;
  24. int val;
  25. }row[MAXN],col[MAXN];
  26. int emp,row_num,col_num;
  27. int lvl[MAXN], gap[MAXN];
  28. int cnt_edge;
  29. int n,m,T;
  30. int empty[MAXN];
  31.  
  32. void Insert_Edge( int u , int v , int flow = ) {
  33.  
  34. edge[cnt_edge] = Edge(v,head[u],flow);
  35. head[u] = cnt_edge++;
  36. edge[cnt_edge] = Edge(u,head[v]);
  37. head[v] = cnt_edge++;
  38.  
  39. }
  40.  
  41. void Init(){
  42. cnt_edge = ;
  43. memset(head,-,sizeof(head));
  44. memset(lvl, , sizeof (lvl));
  45. memset(gap, , sizeof (gap));
  46. }
  47.  
  48. int dfs(int u, int flow)
  49. {
  50. if (u==ed) {
  51. return flow;
  52. }
  53. int tf = , sf, mlvl = ed-;
  54. for (int i= head[u]; i != -; i = edge[i].next) {
  55. if (edge[i].val > ) {
  56. if (lvl[u] ==lvl[edge[i].v]+) {
  57. sf = dfs(edge[i].v, min(flow-tf, edge[i].val));
  58. edge[i].val -= sf;
  59. edge[RE(i)].val += sf;
  60. tf += sf;
  61. if (lvl[st] >=ed) {
  62. return tf;
  63. }
  64. if (tf == flow) {
  65. break;
  66. }
  67. }
  68. mlvl = min(mlvl, lvl[edge[i].v]);
  69. }
  70. }
  71. if (tf == ) {
  72. --gap[lvl[u]];
  73. if (!gap[lvl[u]]) {
  74. lvl[st] =ed;
  75. }
  76. else {
  77. lvl[u] = mlvl+;
  78. ++gap[lvl[u]];
  79. }
  80. }
  81. return tf;
  82. }
  83.  
  84. int sap()
  85. {
  86. int ans = ;
  87. gap[]=ed;
  88. while (lvl[st] <ed) {
  89. ans += dfs(st, INF);
  90. }
  91. return ans;
  92. }
  93.  
  94. int print( int tp ) {
  95. int ans = ;
  96. int id = tp + row_num+;
  97. for( int i = head[id] ; i != - ; i = edge[i].next ) {
  98. int v = edge[i].v;
  99. if( v <=row_num+ )
  100. {
  101. ans+= edge[i].val;
  102. break;
  103. }
  104. }
  105. return ans+;
  106. }
  107.  
  108. int main()
  109.  
  110. {
  111.  
  112. int i,j;
  113.  
  114. char s[];
  115.  
  116. while(scanf("%d%d",&n,&m)!=-)
  117. {
  118. emp=row_num=col_num=;
  119. for(i=;i<n;i++)
  120. for(j=;j<m;j++)
  121. {
  122. scanf("%s",s);
  123. if(s[]=='.')
  124. {
  125. map[i][j]=++emp;
  126. }
  127. else
  128. {
  129. map[i][j]=-;
  130. if(s[]!='X')
  131. {
  132. int tp=(s[]-'')*+(s[]-'')*+s[]-'';
  133. row[++row_num].x=i;
  134. row[row_num].y=j;
  135. row[row_num].val=tp;
  136.  
  137. }
  138. if(s[]!= 'X' ) {
  139. int tp = (s[]-'')*+(s[]-'')*+s[]-'';
  140. col[++col_num].x = i;
  141. col[col_num].y = j;
  142. col[col_num].val = tp;
  143. }
  144.  
  145. }
  146.  
  147. }
  148. T=emp+col_num+row_num+;
  149. st=;
  150. ed=T;
  151. Init();
  152. for(i=;i<=row_num;i++)
  153. {
  154. int pos = i;
  155. int x = row[i].x;
  156. int y = row[i].y;
  157. int cnt_len = ;
  158. for( y=y+; y <m ; y++ ) {
  159. if( map[x][y] != - ) {
  160. cnt_len++;
  161. Insert_Edge(i+, row_num+ map[x][y]+,);
  162. } else break;
  163. }
  164. Insert_Edge(st,pos+,row[i].val-cnt_len);
  165. }
  166.  
  167. for( i = ; i <=col_num ; i++ ) {
  168. int pos =i++row_num+emp;
  169. int x = col[i].x;
  170. int y = col[i].y;
  171. int cnt_len = ;
  172. for( x=x+ ; x < n ; x++ ) {
  173. if( map[x][y] != - ) {
  174. cnt_len++;
  175. Insert_Edge(row_num+ map[x][y]+,pos,);
  176.  
  177. } else break;
  178. }
  179. Insert_Edge(pos,ed,col[i].val-cnt_len);
  180. }
  181. sap();
  182. for(i=;i<n;i++)
  183. {
  184. for(j=;j<m;j++)
  185. {
  186.  
  187. if(map[i][j]==-)
  188. printf("_ ");
  189. else
  190. printf("%d ",print(map[i][j]));
  191. }
  192. printf("\n");
  193. }
  194. }
  195.  
  196. return ;
  197. }

2015/5/26

kuangbin大法:

  1. /*
  2. * HDU 3338 Kakuro Extension
  3. * 题目意思就是在n*m的格子中,有黑白两种格子。要在白格子中填入数字1~9
  4. * 每一段横竖连续的白格子的和是知道的。
  5. * 求出一种满足的,保证有解。
  6. * 最大流。
  7. * 按照横竖段进行编号。然后行进列出,构造图形。
  8. *
  9. * 为了保证填入的数字是1~9,所以一开始每个格子减掉了1,相应的流入和流出都减掉。
  10. * 然后格子的边的赋值为8.
  11. * 还有就是要记录下相应边的编号,便于输出结果。
  12. *
  13. */
  14.  
  15. #include <iostream>
  16. #include <string.h>
  17. #include <algorithm>
  18. #include <stdio.h>
  19. using namespace std;
  20.  
  21. const int MAXN=;
  22. const int MAXM=;
  23. const int INF=0x3f3f3f3f;
  24. struct Node
  25. {
  26. int to,next,cap;
  27. }edge[MAXM];
  28. int tol;
  29. int head[MAXN];
  30. int gap[MAXN],dis[MAXN],pre[MAXN],cur[MAXN];
  31. void init()
  32. {
  33. tol=;
  34. memset(head,-,sizeof(head));
  35. }
  36. void addedge(int u,int v,int w,int rw=)
  37. {
  38. edge[tol].to=v;edge[tol].cap=w;edge[tol].next=head[u];head[u]=tol++;
  39. edge[tol].to=u;edge[tol].cap=rw;edge[tol].next=head[v];head[v]=tol++;
  40. }
  41. int sap(int start,int end,int nodenum)
  42. {
  43. memset(dis,,sizeof(dis));
  44. memset(gap,,sizeof(gap));
  45. memcpy(cur,head,sizeof(head));
  46. int u=pre[start]=start,maxflow=,aug=-;
  47. gap[]=nodenum;
  48. while(dis[start]<nodenum)
  49. {
  50. loop:
  51. for(int &i=cur[u];i!=-;i=edge[i].next)
  52. {
  53. int v=edge[i].to;
  54. if(edge[i].cap&&dis[u]==dis[v]+)
  55. {
  56. if(aug==-||aug>edge[i].cap)
  57. aug=edge[i].cap;
  58. pre[v]=u;
  59. u=v;
  60. if(v==end)
  61. {
  62. maxflow+=aug;
  63. for(u=pre[u];v!=start;v=u,u=pre[u])
  64. {
  65. edge[cur[u]].cap-=aug;
  66. edge[cur[u]^].cap+=aug;
  67. }
  68. aug=-;
  69. }
  70. goto loop;
  71. }
  72. }
  73. int mindis=nodenum;
  74. for(int i=head[u];i!=-;i=edge[i].next)
  75. {
  76. int v=edge[i].to;
  77. if(edge[i].cap&&mindis>dis[v])
  78. {
  79. cur[u]=i;
  80. mindis=dis[v];
  81. }
  82. }
  83. if((--gap[dis[u]])==)break;
  84. gap[dis[u]=mindis+]++;
  85. u=pre[u];
  86. }
  87. return maxflow;
  88. }
  89.  
  90. char str[][][];
  91. int lx[][];//存横条的标号
  92. int ly[][];//存竖条的标号
  93. int num[];//记录lx,ly数组中出现的次数,因为题目要求填入的数字是1~9,所以先全部变1,相应的流要减少
  94. int id[][];//相应的边的编号,便于最后统计结果
  95.  
  96. int main()
  97. {
  98. //freopen("in.txt","r",stdin);
  99. //freopen("out.txt","w",stdout);
  100. int n,m;
  101. while(scanf("%d%d",&n,&m)==)
  102. {
  103. for(int i=;i<n;i++)
  104. for(int j=;j<m;j++)
  105. scanf("%s",str[i][j]);
  106. init();
  107. int tt=;//结点标号
  108. memset(lx,,sizeof(lx));
  109. memset(ly,,sizeof(ly));
  110. memset(num,,sizeof(num));
  111. for(int i=;i<n;i++)
  112. for(int j=;j<m;j++)
  113. {
  114. if(strcmp(str[i][j],".......")!=)continue;
  115. if(j== || lx[i][j-]==)lx[i][j]=++tt;
  116. else lx[i][j]=lx[i][j-];
  117. num[lx[i][j]]++;
  118. }
  119. for(int j=;j<m;j++)
  120. for(int i=;i<n;i++)
  121. {
  122. if(strcmp(str[i][j],".......")!=)continue;
  123. if(i== || ly[i-][j]==)ly[i][j]=++tt;
  124. else ly[i][j]=ly[i-][j];
  125. num[ly[i][j]]++;
  126. }
  127. int start=,end=tt+,nodenum=tt+;
  128. for(int i=;i<n;i++)
  129. for(int j=;j<m;j++)
  130. if(strcmp(str[i][j],".......")==)
  131. {
  132. addedge(lx[i][j],ly[i][j],);
  133. id[i][j]=tol-;//记录下来
  134. }
  135. for(int i=;i<n;i++)
  136. for(int j=;j<m;j++)
  137. {
  138. if(str[i][j][]!='\\')continue;
  139. if(str[i][j][]!='X')
  140. {
  141. int tmp=(str[i][j][]-'')*+(str[i][j][]-'')*+(str[i][j][]-'');
  142. if(ly[i+][j]!=)
  143. addedge(ly[i+][j],end,tmp-num[ly[i+][j]]);
  144. }
  145. if(str[i][j][]!='X')
  146. {
  147. int tmp=(str[i][j][]-'')*+(str[i][j][]-'')*+(str[i][j][]-'');
  148. if(lx[i][j+]!=)
  149. addedge(start,lx[i][j+],tmp-num[lx[i][j+]]);
  150. }
  151. }
  152. sap(start,end,nodenum);
  153. for(int i=;i<n;i++)
  154. {
  155. for(int j=;j<m;j++)
  156. {
  157. if(j>)printf(" ");
  158. if(strcmp(str[i][j],".......")!=)printf("_");
  159. else printf("%c",''+-edge[id[i][j]].cap);
  160. }
  161. printf("\n");
  162. }
  163. }
  164. return ;
  165. }

hdu 3338 最大流 ****的更多相关文章

  1. HDU 3338 Kakuro Extension (网络流,最大流)

    HDU 3338 Kakuro Extension (网络流,最大流) Description If you solved problem like this, forget it.Because y ...

  2. HDU 1532 最大流入门

    1.HDU 1532 最大流入门,n个n条边,求第1点到第m点的最大流.只用EK做了一下. #include<bits/stdc++.h> using namespace std; #pr ...

  3. HDU - 3338 Kakuro Extension (最大流求解方格填数)

    题意:给一个方格,每行每列都有对白色格子中的数之和的要求.每个格子中的数范围在[1,9]中.现在给出了这些要求,求满足条件的解. 分析:本题读入和建图比较恶心... 用网络流求解.建立源点S和汇点T, ...

  4. L - Kakuro Extension - HDU 3338 - (最大流)

    题意:有一个填数字的游戏,需要你为白色的块内填一些值,不过不能随意填的,是有一些规则的(废话),在空白的上方和作方给出一些值,如果左下角有值说明下面列的和等于这个值,右上角的值等于这行后面的数的和,如 ...

  5. hdu 4289 最大流拆点

    大致题意:     给出一个又n个点,m条边组成的无向图.给出两个点s,t.对于图中的每个点,去掉这个点都需要一定的花费.求至少多少花费才能使得s和t之间不连通. 大致思路:     最基础的拆点最大 ...

  6. Going Home HDU - 1533 费用流

    http://acm.hdu.edu.cn/showproblem.php?pid=1533 给一个网格图,每两个点之间的匹配花费为其曼哈顿距离,问给每个的"$m$"匹配到一个&q ...

  7. hdu 4975 最大流快版

    http://acm.hdu.edu.cn/showproblem.php?pid=4975 给出每行每列的和,问是否存在这样的表格:每个小格放的数字只能是0--9. 直接用第八场最大流模板. #in ...

  8. hdu 4888 最大流慢板

    http://acm.hdu.edu.cn/showproblem.php?pid=4888 添加一个源点与汇点,建图如下: 1. 源点 -> 每一行对应的点,流量限制为该行的和 2. 每一行对 ...

  9. hdu 2732 最大流 **

    题意:题目是说一个n*m的迷宫中,有每个格子有柱子.柱子高度为0~3,高度为0的柱子是不能站的(高度为0就是没有柱子)在一些有柱子的格子上有一些蜥蜴,一次最多跳距离d,相邻格子的距离是1,只要跳出迷宫 ...

随机推荐

  1. Oracle环境变量与中文显示的问题

    在CentOS(linux)下安装Oracle,对环境变量的设置有一些讲究. 一般我们可以把环境变量设置在/etc/profile文件中: # Oracle SettingsTMP=/tmp; exp ...

  2. 读sru代码

    1. def read_corpus(path, eos="</s>"): data = [ ] with open(path) as fin: for line in ...

  3. Oracle Certified Java Programmer 经典题目分析(一)

    Given: 1. public class returnIt { 2. returnType methodA(byte x, double y){ 3. return (short) x/y * 2 ...

  4. ARC073E Ball Coloring

    Problem AtCoder Solution 把点映射至二维平面,问题就变成了给定 \(n\) 个点,可以把点对 \(y=x\) 对称,求覆盖所有点的最小矩形面积. 可以先把所有点放到 \(y=x ...

  5. poj1102

    模拟 #include <iostream> #include <string> using namespace std; ][][] = { { ' ', '-', ' ', ...

  6. Flask:使用Eclipse+PyDev插件编辑基于package的项目

    Windows 10家庭中文版,Python 3.6.4,Flask 1.0.2,Eclipse Oxygen.1a Release (4.7.1a),PyDev 6.3.2 本文记录了 使用Ecli ...

  7. 【前端vue开发】Hbuilder配置Avalon、AngularJS、Vue指令提示

    偶尔也会研究一下前端内容,因为Hbuilder是基于eclipse开发的,所以用起来倍感亲切啊,而且在我尝试使用的几款前端开发工具中,Hbuilder的表现也是相当出色地,可以访问Huilder官网下 ...

  8. SQL Server操作实例

    创建数据库 create database accountInfo/*创建账户信息数据库*/ 创建数据表 /*定义主码.外码.和人数.余额的取值范围.*/ /*创建储蓄所表*/ create tabl ...

  9. python学习day4软件目录结构规范

    为什么要设计好目录结构? 参考:http://www.cnblogs.com/alex3714/articles/5765046.html "设计项目目录结构",就和"代 ...

  10. ajax传递的参数服务器端接受不到的原因

    最常见的就是组织的json数据格式有问题,尝试把单引号改为双引号试试,如下: $datares = {"uname":$uname.val(),"phone": ...