HDU 3338 Kakuro Extension

这一题花了我一晚上才搞定,不过蛮开心的。

题目大意:

原数谜是个很有趣的游戏,如图,每一行或每一列空白称为一个回,每一回都对应着一个整数sum,sum就是这回的和。这些空白格里只能填入1—9这九个数字,且在每一回中不能重复。全黑色的格为空,有数字的格,左下角的表示列的和,右上角的表示行的和,则可以得到下面这个图。

但这道题不是原来的数谜,这题与原数谜相比,少了一点规则,就是,每一回中出现的数字可以重复。给你一个n * m 的图,让你填充一下。

这题可以用网络流做。以空白格为节点,假设流是从左流入,从上流出的,流入的容量为行和,流出来容量为列和,其余容量不变。求满足的最大流。由于流量有上下限限制,可以给每个数都减掉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。

我的代码如下:

用的是sap算法,218ms通过

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

 

 

 

posted on 2012-08-16 22:49  我的ACM之路  阅读(733)  评论(0编辑  收藏  举报

导航