题目链接: Kakuro Extension HDU - 3338
题目大意
一个如图所示的矩阵, 有数字的黑色方块左下角的数字表示从这个方块下面一个方块开始一直到边界或另一个黑色方块所有白色方块的数字和, 黑色方块右上角表示右边所有白色方块的数字和
给所有白色方块填上数字(1-9)
思路
和紫书矩阵解压那题一样, 当时更复杂一些, 同样要把每个白色方块的数字减去1后再处理, 每个黑色方块向其下方的白色方块连边, 容量INF, 每个白色方块向其左边的黑色方块连边, 容量INF, 源点S向每个黑色方块连边, 容量为黑色方块左下角数字减去其下方白色方块数量, 每个黑色方块向汇点T连边, 容量为右上角数字减去其右边白色方块数量, 每个白色方块拆成两个, 之间连一条容量为8的边, 求S-T最大流, 然后每个白色方块两个顶点间的流量+1就是白块的数字
一直WA找不出BUG, 以后再写吧
代码(WA)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
using namespace std;
const int MAXV = 100000, INF = 0X3F3F3F3F;
struct edge
{
int to, cap, rev;
edge(int a, int b, int c) :to(a), cap(b), rev(c){}
};
vector<edge> G[MAXV];
int iter[MAXV], level[MAXV], S, T;
void add_edge(int from, int to, int cap)
{
G[from].push_back(edge(to, cap, G[to].size()));
G[to].push_back(edge(from, 0, G[from].size()-1));
}
bool bfs()
{
memset(level, -1, sizeof(level));
level[S] = 0;
queue<int> que;
que.push(S);
while(!que.empty())
{
int v = que.front(); que.pop();
for(int i=0; i<(int)G[v].size(); ++i)
{
edge &e = G[v][i];
if(e.cap>0 && level[e.to]==-1)
{
level[e.to] = level[v] + 1;
que.push(e.to);
}
}
}
return level[T]!=-1;
}
int dfs(int v, int f)
{
if(v == T) return f;
for(int &i=iter[v]; i<(int)G[v].size(); ++i)
{
edge &e = G[v][i];
if(e.cap>0 && level[e.to]>level[v])
{
int d = dfs(e.to, min(f, e.cap));
if(d)
{
e.cap -= d;
G[e.to][e.rev].cap+= d;
return d;
}
}
}
return 0;
}
int max_flow()
{
int flow = 0;
while(bfs())
{
memset(iter, 0, sizeof(iter));
int f;
while((f=dfs(S, INF))) flow += f;
}
return flow;
}
void init()
{
for(int i=0; i<MAXV; ++i) G[i].clear();
}
const int MAXN = 500;
int n, m;
struct P
{
int d, r, id1, id2;
void in()
{
id1 = id2 = -1;
char s[10];
scanf("%s", s);
for(int i=0; s[i]!='\0'; ++i)
if(s[i] == 'X') s[i] = '1';
else if(s[i] == '.') s[i] = '0';
s[3] = ' ';
sscanf(s, "%d%d", &d, &r);
if(d == 111) d = -1;
if(r == 111) r = -1;
}
};
P p[MAXN][MAXN];
int main()
{
while(scanf("%d%d", &n, &m) == 2)
{
init();
for(int i=0; i<n; ++i)
for(int j=0; j<m; ++j) p[i][j].in();
int cnt = 0;
S = cnt++;
T = cnt++;
for(int i=0; i<n; ++i)
{
for(int j=0; j<m; ++j)
{
if(p[i][j].r > 0)
{
if(p[i][j].id1 == -1) p[i][j].id1 = cnt++;
for(int k=j+1; p[i][k].d==0 && p[i][k].r==0 && k<m; ++k)
{
if(p[i][k].id1 == -1) p[i][k].id1 = cnt++;
add_edge(p[i][j].id1, p[i][k].id1, INF);
p[i][j].r--;
}
add_edge(S, p[i][j].id1, p[i][j].r);
}
if(p[i][j].d > 0)
{
if(p[i][j].id2 == -1) p[i][j].id2 = cnt++;
for(int k=i+1; p[k][j].d==0&&p[k][j].r==0 && k<n; ++k)
{
if(p[k][j].id2==-1) p[k][j].id2 =cnt++;
add_edge(p[k][j].id2, p[i][j].id2, INF);
p[i][j].d--;
}
add_edge(p[i][j].id2, T, p[i][j].d);
}
if(p[i][j].r==0 && p[i][j].d==0)
{
if(p[i][j].id1==-1) p[i][j].id1 = cnt++;
if(p[i][j].id2==-1) p[i][j].id2 = cnt++;
add_edge(p[i][j].id1, p[i][j].id2, 8);
}
}
}
max_flow();
int ans[MAXN][MAXN];
memset(ans, -1, sizeof(ans));
for(int i=0; i<n; ++i)
{
for(int j=0; j<m; ++j)
{
if(p[i][j].r==0 && p[i][j].d==0)
{
int x = p[i][j].id1;
int y = p[i][j].id2;
for(auto &e: G[x])
{
if(e.to == y)
{
ans[i][j] = 8-abs(e.cap)+1;
}
}
}
}
}
for(int i=0; i<n; ++i)
{
for(int j=0; j<m; ++j)
if(ans[i][j]==-1) printf("_%c", j==m-1?'\n':' ');
else printf("%d%c", ans[i][j], j==m-1?'\n':' ');
}
}
return 0;
}