poj openjudge 1036 gugle seating

传送门点击打开链接

题目大意 :给出n*m的矩阵,若矩阵该位置为1,则为一个人,若为2则为一台电脑,若为0,则为空地,求最大匹配人数。

(匹配的意思是如果一个人相邻有两台电脑,且这两台电脑不在同一行或者同一列,即人,两台电脑在矩阵中构成了‘L’型,则算一种匹配,一台电脑只能和一个人匹配。)

(n,m<=500)

 

思路:首先我们意识到一个人所匹配的电脑一定是不同行的,即不同奇偶,奇偶让我们想到了什么?二分图匹配,选一个匹配的过程就变成了选一个奇数行的电脑->选一个与该电脑相邻的人->再选一个与这个人相邻的偶数行的电脑….

所以我们就连上<s,odd,1>,<odd,person,1>,<preson,even,1>三种边,然后最大流跑就是了。

是吗?当然不是上面那样、

如果我们这样连边跑最大流,那么一个人可能会被用到两次?所以明显是错的!!!

(当时真的是wa死我了…..)。

怎么解决呢?我们这样连边:

<s,odd,1>,<odd,person_in,1>,<preson_in,preson_out,1>,<person_out,even,1>,<even,t,1>/

什么意思呢?我们将每个人拆成两个点,一个流入,一个流出,流入点和流出点连一条流量为1的边,就可以限制每个人只匹配一次了..(我居然连这个都没想到….)。

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<ctime>
#define inf 1000000000
using namespace std;
struct edge{int to;int next;int flow;
};edge bian[5000010];
int size=1,first[3000010],head,tail,dis[3000010],p[5000010],s,t,n,m,A[550][550];
bool exist[3000010];
int pos1(int x,int y) {return (x-1)*m+y;}
int pos2(int x,int y) {return m*n+(x-1)*m+y;}
void inser(int x,int y,int z) {
	bian[++size].to=y;
	bian[size].next=first[x];
	bian[size].flow=z;
	first[x]=size;
	
	bian[++size].to=x;
	bian[size].next=first[y];
	bian[size].flow=0;
	first[y]=size;
}
bool bfs(int x,int y) {
	memset(dis,127,sizeof(dis));
	dis[x]=0;
    head=0,tail=1;p[1]=x;
    memset(exist,false,sizeof(exist));
    while(head!=tail)
    {
    	int k=p[++head];
    	exist[k]=false;
    	for(int u=first[k];u;u=bian[u].next) 
    	{
    		if(dis[bian[u].to]>=9000000&&bian[u].flow>0)
    		{
    			dis[bian[u].to]=dis[k]+1;
    			if(!exist[bian[u].to])
    			{
    				p[++tail]=bian[u].to;
    				exist[bian[u].to]=true;
    			}
    		}
    	}
    }
    return dis[y]<=9000000;
}
int dfs(int x,int F) {
	if(x==t) return F;
	int ret=0;
	for(int u=first[x];u&&F>0;u=bian[u].next)
	{
		if(bian[u].flow>0&&dis[bian[u].to]==dis[x]+1)
		{
			int f=dfs(bian[u].to,min(F,bian[u].flow));
			F-=f;
			bian[u].flow-=f;
			bian[u^1].flow+=f;
			ret+=f;
		}
	}
	if(F==0||ret==0) dis[x]=-5;
	return ret;
}
int maxflow(int x,int y) {
	int ret=0;
	while(bfs(x,y)) ret+=dfs(x,1000000000);
	return ret;
}
int main()
{
	freopen("gugleseating.in","r",stdin);
	freopen("gugleseating.out","w",stdout);
	scanf("%d%d",&n,&m);
	memset(A,0,sizeof(A));
	for(int i=1;i<=n;i++) 
	    for(int j=1;j<=m;j++)
	    	scanf("%d",&A[i][j]);
	s=0,t=2*n*m+1;
	for(int i=1;i<=n;i++)
	    for(int j=1;j<=m;j++)
	    {
	    	if(A[i][j]==2)
	    	{
	    		if(i%2==1)
	    		{
	    			inser(s,pos1(i,j),1);
	    			if(A[i-1][j]==1&&i-1>=1) inser(pos1(i,j),pos1(i-1,j),1);
	    			if(A[i][j-1]==1&&j-1>=1) inser(pos1(i,j),pos1(i,j-1),1);
	    			if(A[i][j+1]==1&&j+1<=m) inser(pos1(i,j),pos1(i,j+1),1);
	    			if(A[i+1][j]==1&&i+1<=n) inser(pos1(i,j),pos1(i+1,j),1);
	    		}
	    		else 
	    		{
	    			inser(pos1(i,j),t,1);
	    		    if(A[i-1][j]==1&&i-1>=1) inser(pos2(i-1,j),pos1(i,j),1);
	    			if(A[i][j-1]==1&&j-1>=1) inser(pos2(i,j-1),pos1(i,j),1);
	    			if(A[i][j+1]==1&&j+1<=m) inser(pos2(i,j+1),pos1(i,j),1);
	    			if(A[i+1][j]==1&&i+1<=n) inser(pos2(i+1,j),pos1(i,j),1);
	    		}
	    	}
	    	else if(A[i][j]==1) inser(pos1(i,j),pos2(i,j),1);
	    }
	cout<<maxflow(s,t);
	return 0;
}


内容概要:本文介绍了MATLAB实现DBN-RBF深度置信网络结合RBF神经网络多输入单输出回归预测的详细项目实例。项目旨在通过深度置信网络(DBN)和径向基函数神经网络(RBF)的结合,设计出一种高效的回归预测模型,以应对高维数据和非线性关系的挑战。DBN用于无监督特征提取,RBF用于快速回归,两者结合显著提升了预测精度和模型泛化能力。文中详细描述了项目的背景、目标、挑战、解决方案、模型架构、代码实现、GUI设计、性能评估及未来改进方向。 适合人群:具备一定编程基础,对机器学习和深度学习有一定了解的研发人员,尤其是从事金融预测、医疗健康、智能制造等领域的工程师和技术人员。 使用场景及目标:①解决高维数据的特征提取难题,提升非线性回归的拟合精度;②通过无监督学习与快速训练能力的结合,提高模型的预测精度和泛化能力;③应用于金融预测、医疗健康、智能制造等多个领域,提供高效的回归预测工具;④通过实时数据流处理和GPU加速推理,确保系统在实时应用中的快速响应。 其他说明:此项目不仅提供了详细的理论分析和代码实现,还涵盖了系统架构设计、模型部署与应用、安全性与用户隐私保护等方面的全面指导。通过结合其他深度学习模型、多任务学习、增量学习等技术,项目具备广阔的扩展性和应用前景。系统还支持自动化CI/CD管道、API服务与业务集成、前端展示与结果导出等功能,确保了系统的高可用性和易用性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值