2656: 霍格瓦兹魔法阵
Result | TIME Limit | MEMORY Limit | Run Times | AC Times | JUDGE |
---|---|---|---|---|---|
2s | 32768K | 89 | 13 | Standard |
最近,伏地魔开始网罗党羽, 许多女巫和男巫为了获得他赋予的力量加入了他的阵营。为了抵抗伏地魔的进攻,霍格瓦兹的魔法师们摆出了一个 n * m 方格的魔法方阵,每个方格中都站有一位魔法师。当然,魔法师们都有自己的魔法值,用非负整数表示。 然而,对伏地魔发起攻击时,为了安全起见,任意两个相邻的魔法师 (上下相邻或左右相邻) 不能同时施展魔法。为了打败强大的伏地魔,你能帮助霍格瓦兹的魔法师们找出最大可能的攻击魔法值么?
输入含有多组case 每个case的第一行有两个整数 n 和 m ,代表魔法方阵的规模接下来输入的是 n * m 的非负整数矩阵。 n和m均不超过50 当n=m=0时,输入结束
对每个case, 输出最大可能魔法值
3 2 1 2 3 4 5 6 3 3 75 15 21 75 15 28 34 70 5 0 0
11 188
Problem Source: ccst
This problem is used for contest: 162
Submit / Problem List / Status / Discuss
#include<cstdio>
#include<cstring>
const int MAXN=2510;
const int MAXM=20000;
const int INF = 0x7fffffff;
struct Edge
{
int st, ed,next,flow;
} edge[MAXM];
int head[MAXN],value[MAXN];
int N, M, F, E;
int src, dest;
int seq[MAXM], sl;
int ans = 0;
int map[101][101];
void add_edge(int u, int v, int w)
{
edge[E].flow = w;
edge[E].st = u;
edge[E].ed = v;
edge[E].next = head[u];
head[u] = E++;
edge[E].flow = 0;
edge[E].st = v;
edge[E].ed = u;
edge[E].next = head[v];
head[v] = E++;
}
int d[MAXN];
bool dinic_bfs(void)
{
int i, j;
memset(d, -1, sizeof(d));
int que[MAXN], rear = 1;
que[0] = src;
d[src] = 0;
for(i = 0; i < rear; i++)
{
for(j = head[que[i]]; j != -1; j = edge[j].next)
{
if(d[edge[j].ed] == -1 && edge[j].flow > 0)
{
d[edge[j].ed] = d[que[i]]+1;
que[rear++] = edge[j].ed;
if(edge[j].ed==dest) return true;
}
}
}
return false;
}
int dinic_dfs(void)
{
int stk[MAXN], top = 0;
int ret = 0, cur, ptr, pre[MAXN], minf, i;
bool del[MAXN];
memset(del, false, sizeof(del));
stk[top++] = src;
pre[src] = src;
cur = src;
while(top)
{
while(cur != dest && top)
{
for(i = head[cur]; i != -1; i = edge[i].next)
{
if(d[edge[i].ed] == d[cur]+1 && edge[i].flow > 0 && !del[edge[i].ed])
{
stk[top++] = edge[i].ed;
cur = edge[i].ed;
pre[edge[i].ed] = i;
break;
}
}
if(i == -1)
{
del[cur] = 1;
top--;
if(top) cur = stk[top-1];
}
}
if(cur == dest)
{
minf = INF;
while(cur != src)
{
cur = pre[cur];
if(edge[cur].flow < minf)
minf = edge[cur].flow;
cur = edge[cur].st;
}
cur = dest;
while(cur != src)
{
cur = pre[cur];
edge[cur].flow -= minf;
edge[cur^1].flow += minf;
if(edge[cur].flow == 0)
ptr = edge[cur].st;
cur = edge[cur].st;
}
while(top > 0&& stk[top-1] != ptr) top--;
if(top) cur = stk[top-1];
ret += minf;
}
}
return ret;
}
int Dinic()
{
int ret = 0, t;
while(dinic_bfs())
{
t = dinic_dfs();
if(t) ret += t;
else break;
}
return ret;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0) break;
src=0;
dest=n*m+1;
E=0;
memset(head,-1,sizeof(head));
int sum=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&map[i][j]);
sum+=map[i][j];
}
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
{
int t=(i-1)*m+j;
if((i+j)%2==0)
{
add_edge(0,t,map[i][j]);
if(i+1<=n) add_edge(t,t+m,INF);
if(j+1<=m) add_edge(t,t+1,INF);
}
else
{
add_edge(t,n*m+1,map[i][j]);
if(i+1<=n) add_edge(t+m,t,INF);
if(j+1<=m) add_edge(t+1,t,INF);
}
}
printf("%d/n",sum-Dinic());
}
return 0;
}