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 }


浙公网安备 33010602011771号