[HDU 1565+1569] 方格取数

时间:2023-03-08 23:56:08
[HDU 1565+1569] 方格取数

HDU 1565

方格取数(1)

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5961    Accepted Submission(s): 2268

Problem Description
给你一个n*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。
Input
包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20)
Output
对于每个测试实例,输出可能取得的最大的和
Sample Input
3
75 15 21
75 15 28
34 70 5
Sample Output
188
最大点权独立集
弱弱的EK算法
邻接矩阵实现 124MS
邻接表实现 15MS
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <set>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
#define INF 0x3f3f3f3f
#define ll long long
#define N 510 int n;
int src;
int des;
int sum;
int pre[N];
int mpt[N][N];
int map[N][N];
int dir[][]={,,-,,,,,-};
queue<int> q; bool bfs()
{
while(!q.empty()) q.pop();
memset(pre,-,sizeof(pre));
pre[src]=;
q.push(src);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int v=;v<=n*n+;v++)
{
if(pre[v]==- && mpt[u][v]>)
{
pre[v]=u;
if(v==des) return ;
q.push(v);
}
}
}
return ;
}
int EK()
{
int maxflow=;
while(bfs())
{
int minflow=INF;
for(int i=des;i!=src;i=pre[i])
minflow=min(minflow,mpt[pre[i]][i]);
maxflow+=minflow;
for(int i=des;i!=src;i=pre[i])
{
mpt[pre[i]][i]-=minflow;
mpt[i][pre[i]]+=minflow;
}
}
return maxflow;
}
int main()
{
int i,j,k;
while(scanf("%d",&n)!=EOF)
{
sum=;
memset(mpt,,sizeof(mpt));
for(i=;i<=n;i++)
{
for(j=;j<=n;j++)
{
scanf("%d",&map[i][j]);
sum+=map[i][j];
}
}
src=;
des=n*n+;
for(i=;i<=n;i++)
{
for(j=;j<=n;j++)
{
if((i+j)%==) mpt[src][(i-)*n+j]=map[i][j];
else mpt[(i-)*n+j][des]=map[i][j];
}
}
for(i=;i<=n;i++)
{
for(j=;j<=n;j++)
{
if((i+j)%==)
{
for(k=;k<;k++)
{
int x=i+dir[k][];
int y=j+dir[k][];
if(x>= && x<=n && y>= && y<=n)
{
mpt[(i-)*n+j][(x-)*n+y]=INF;
}
}
}
}
}
printf("%d\n",sum-EK());
}
return ;
}

HDU 1569

和方格取数1数据大小不一样,用上面的会超时,可能是写搓了。

邻接表实现 280ms

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <set>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
#define INF 0x3f3f3f3f
#define ll long long
#define N 20510 struct Edge
{
int to,next,val;
}edge[N];
int tot;
int head[N]; int n;
int m;
int src;
int des;
int sum;
int pre[N];
int path[N];
int map[N][N];
int dir[][]={,,-,,,,,-};
queue<int> q; void init()
{
tot=;
memset(head,-,sizeof(head));
}
void add(int u,int v,int w)
{
edge[tot].to=v;
edge[tot].val=w;
edge[tot].next=head[u];
head[u]=tot++; edge[tot].to=u;
edge[tot].val=;
edge[tot].next=head[v];
head[v]=tot++; }
bool bfs()
{
while(!q.empty()) q.pop();
memset(pre,-,sizeof(pre));
pre[src]=;
q.push(src);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].to;
if(pre[v]==- && edge[i].val>)
{
pre[v]=u;
path[v]=i;
if(v==des) return ;
q.push(v);
}
}
}
return ;
}
int EK()
{
int maxflow=;
while(bfs())
{
int minflow=INF;
for(int i=des;i!=src;i=pre[i])
minflow=min(minflow,edge[path[i]].val);
maxflow+=minflow;
for(int i=des;i!=src;i=pre[i])
{
edge[path[i]].val-=minflow;
edge[path[i]^].val+=minflow;
}
}
return maxflow;
}
int main()
{
int i,j,k;
while(scanf("%d%d",&n,&m)!=EOF)
{
sum=;
init();
for(i=;i<=n;i++)
{
for(j=;j<=m;j++)
{
scanf("%d",&map[i][j]);
sum+=map[i][j];
}
}
src=;
des=n*m+;
for(i=;i<=n;i++)
{
for(j=;j<=m;j++)
{
if((i+j)%==) add(src,(i-)*m+j,map[i][j]);
else add((i-)*m+j,des,map[i][j]);
}
}
for(i=;i<=n;i++)
{
for(j=;j<=m;j++)
{
if((i+j)%==)
{
for(k=;k<;k++)
{
int x=i+dir[k][];
int y=j+dir[k][];
if(x>= && x<=n && y>= && y<=m)
{
add((i-)*m+j,(x-)*m+y,INF);
}
}
}
}
}
printf("%d\n",sum-EK());
}
return ;
}