题意:题目是给出类似图片那样的网格,在空白格子填入一个数,使行和或者列和等于黑格子中的数,每个格子填入的数在1-9分为内,找出任意一个满足的解。
建图:
sp-左-空白-上-tp(sp-上-空-左-tp)
总共5种点
1.type=0 黑格
2.type=1 空格
3.type=2 有两个数字的格子
4.type=3 只有上边数字的格子
5.type=4 只有左边数字的格子
左进上出
然后建边 虚构源点sp,汇点tp
1.源点与type24相连,容量为左边的数字-这个格子管辖的空格数*1
2.type24与他管辖的空格相连,容量为8,
0-8分别代表数字1-9 这样我们就把填格子转化成了网络流中边的关系
3.空格与管辖他的type23空格相连,容量为8
4.type23与汇点相连,容量为上边的数字-这个格子管辖的空格数*1
然后计算一遍最大流
每个格子上面的数字就是这个数字 8-这个数字上面边的流量+1
链接:hdu 3338
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#define INF 0x3f3f3f3f
//#define ll long long
#define MAXN 100005
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 100005;
struct node {
int type, a, b, id;
}ma[105][105];
int n, m;//点数、边数
int sp, tp;//原点、汇点
struct node1 {
int v, next;
int cap;
}mp[maxn];
int pre[MAXN], dis[MAXN], cur[MAXN];//cur为当前弧优化,dis存储分层图中每个点的层数(即到原点的最短距离),pre建邻接表
int cnt = 0;
void init() { //不要忘记初始化
cnt = 0;
memset(pre, -1, sizeof(pre));
}
void add(int u, int v, int w) { //加边
mp[cnt].v = v;
mp[cnt].cap = w;
mp[cnt].next = pre[u];
pre[u] = cnt++;
mp[cnt].v = u;
mp[cnt].cap = 0;
mp[cnt].next = pre[v];
pre[v] = cnt++;
}
bool bfs() { //建分层图
memset(dis, -1, sizeof(dis));
queue<int>q;
while(!q.empty())
q.pop();
q.push(sp);
dis[sp] = 0;
int u, v;
while(!q.empty()) {
u = q.front();
q.pop();
for(int i = pre[u]; i != -1; i = mp[i].next) {
v = mp[i].v;
if(dis[v] == -1 && mp[i].cap>0) {
dis[v] = dis[u] + 1;
q.push(v);
if(v == tp)
break;
}
}
}
return dis[tp] != -1;
}
int dfs(int u,int cap) {//寻找增广路
if(u == tp || cap == 0)
return cap;
int res = 0, f;
for(int &i = cur[u]; i != -1; i = mp[i].next) {//
int v = mp[i].v;
if(dis[v] == dis[u] + 1 && (f = dfs(v, min(cap - res, mp[i].cap))) > 0) {
mp[i].cap -= f;
mp[i ^ 1].cap += f;
res += f;
if(res == cap)
return cap;
}
}
if(!res)
dis[u] = -1;
return res;
}
int dinic() {
int ans = 0;
while(bfs()) {
for(int i = sp; i <= tp; i++)
cur[i] = pre[i];
ans += dfs(sp, inf);
}
return ans;
}
int g[100005];
void outputgraph()
{
memset(g, 0, sizeof(g));
int s = 0;
for(int i = pre[s]; i != -1; i = mp[i].next)
{
int u = mp[i].v;
for(int j = pre[u]; j != -1; j = mp[j].next)
g[mp[j].v] = 8 - mp[j].cap + 1;
}
for(int i = 1; i <= n; i++)
{
printf("_");
for(int j = 2; j <= m; j++)
{
if(ma[i][j].type == 1)
printf("%2d", g[ma[i][j].id]);
else
printf(" _");
}
printf("\n");
}
}
int main()
{
int t, kcase = 0;
while(scanf("%d %d", &n, &m) != EOF) {
char str[10];
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
scanf("%s", str);
if(str[3] == '.') {
ma[i][j].type = 1;
ma[i][j].a = ma[i][j].b = 0;
}
else if(str[3] == 'X') {
ma[i][j].type = 0;
ma[i][j].a = ma[i][j].b = 0;
ma[i][j].id = 0;
}
else {
if(str[0] != 'X') {
if(str[4] != 'X') {
ma[i][j].type = 2;
ma[i][j].a = (str[2] - '0') + (str[1] - '0') * 10 + (str[0] - '0') * 100;
ma[i][j].b = (str[6] - '0') + (str[5] - '0') * 10 + (str[4] - '0') * 100;
}
else {
ma[i][j].type = 3;
ma[i][j].a = (str[2] - '0') + (str[1] - '0') * 10 + (str[0] - '0') * 100;
}
}
else {
ma[i][j].type = 4;
ma[i][j].a = (str[6] - '0') + (str[5] - '0') * 10 + (str[4] - '0') * 100;
}
}
}
}
int num = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j<= m; j++) {
if(ma[i][j].type > 0) {
if(ma[i][j].type == 2) {
num += 2;
}
else {
num++;
}
ma[i][j].id = num;
}
}
}
sp = 0, tp = num + 1;
init();
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(ma[i][j].type == 3) {
int tot = 0;
for(int k = i + 1; k <= n; k++) {
if(ma[k][j].type != 1) {
break;
}
add(ma[k][j].id, ma[i][j].id, 8);
tot++;
}
add(ma[i][j].id, tp, ma[i][j].a - tot);
}
else if(ma[i][j].type == 4) {
int tot = 0;
for(int k = j + 1; k <= m; k++) {
if(ma[i][k].type != 1) {
break;
}
add(ma[i][j].id, ma[i][k].id, 8);
tot++;
}
add(sp, ma[i][j].id, ma[i][j].a - tot);
}
else if(ma[i][j].type == 2) {
int tot = 0;
for(int k = i + 1; k <= n; k++) {
if(ma[k][j].type != 1) {
break;
}
add(ma[k][j].id, ma[i][j].id - 1, 8);
tot++;
}
add(ma[i][j].id - 1, tp, ma[i][j].a - tot);
tot = 0;
for(int k = j + 1; k <= m; k++) {
if(ma[i][k].type != 1) {
break;
}
add(ma[i][j].id, ma[i][k].id, 8);
tot++;
}
add(sp, ma[i][j].id, ma[i][j].b - tot);
}
}
}
int ans = dinic();
//cout << ans << endl;
outputgraph();
}
return 0;
}
题目是给出类似图片那样的网格,在空白格子填入一个数,使行和或者列和等于黑格子中的数,每个格子填入的数在1-9分为内,找出任意一个满足的解。
本文介绍了一种使用网络流算法解决网格填数问题的方法。该问题要求在空白格子中填入数字,使得每行或每列的数字之和等于指定值。通过构建特定的图模型,并利用Dinic算法求解最大流,可以找到满足条件的一种填数方案。
876

被折叠的 条评论
为什么被折叠?



