您的位置:首页 > 其它

BZOJ1475方格取数

2016-03-12 19:51 288 查看
1475: 方格取数

Time Limit: 5 Sec Memory Limit: 64 MB

Submit: 710 Solved: 361

Description

在一个n*n的方格里,每个格子里都有一个正整数。从中取出若干数,使得任意两个取出的数所在格子没有公共边,且取出的数的总和尽量大。

Input

第一行一个数n;(n<=30) 接下来n行每行n个数描述一个方阵

Output

仅一个数,即最大和

Sample Input

2

1 2

3 5

Sample Output

6

如果x+y为奇数,(x,y)->T,容量v[x,y]

如果x+y为偶数,S->(x,y),容量v[x,y]

并向四个方向的点连边,容量inf

答案为总收益减去最小割

附上本蒟蒻的代码:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define inf 0x7fffffff
int n,xx[4]={0,0,1,-1},yy[4]={1,-1,0,0},map[31][31],mark[31][31],h[10001],dis[10001],q[10001],head,tail,cnt=1,ans=0,sum;
struct kx
{
int to,next,v;
}edge[10001];

bool pd(int x,int y)
{
if (x<1 || y<1 || x>n || y>n) return false;
else return true;
}

int read()
{
int w=0,c=1; char ch=getchar();
while (ch<'0' || ch>'9')
{
if (ch=='-') c=-1;
ch=getchar();
}
while (ch>='0' && ch<='9')
w=w*10+ch-'0',ch=getchar();
return w*c;
}

void add(int u,int v,int w)
{
cnt++,edge[cnt].next=h[u],h[u]=cnt,edge[cnt].to=v,edge[cnt].v=w;
cnt++,edge[cnt].next=h[v],h[v]=cnt,edge[cnt].to=u,edge[cnt].v=0;
}

bool bfs()
{
int j,p;
memset(dis,-1,sizeof(dis));
q[0]=0;
dis[0]=0;
head=0;
tail=1;
while (head<tail)
{
head++;
j=q[head];
p=h[j];
while (p)
{
if (dis[edge[p].to]<0 && edge[p].v>0)
{
dis[edge[p].to]=dis[j]+1;
tail++;
q[tail]=edge[p].to;
}
p=edge[p].next;
}
}
if (dis[n*n+1]>0)
return true;
else
return false;
}

int dfs(int x,int f)
{
int w,used=0,i=h[x];
if (x==n*n+1)
return f;
while (i)
{
if (edge[i].v && dis[edge[i].to]==dis[x]+1)
{
w=f-used;
w=dfs(edge[i].to,min(w,edge[i].v));
edge[i].v-=w;
edge[i^1].v+=w;
used+=w;
if (used==f)
return f;
}
i=edge[i].next;
}
if (!used)
dis[x]=-1;
return used;
}

int main()
{
int i,j,b=0,w,k;
n=read();
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
map[i][j]=read(),ans+=map[i][j];
w=(n*n+1)/2;
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
if ((i+j)%2==0)
b++,mark[i][j]=b;
else
w++,mark[i][j]=w;
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
if ((i+j)%2==0)
{
add(0,mark[i][j],map[i][j]);
for (k=0;k<4;k++)
if (pd(i+xx[k],j+yy[k]))
add(mark[i][j],mark[i+xx[k]][j+yy[k]],inf);
}
else
add(mark[i][j],n*n+1,map[i][j]);
while (bfs())
while (sum=dfs(0,inf))
ans-=sum;
printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: