[网络流24题-6]孤岛营救问题

孤岛营救问题

为什么又是奇奇怪怪的混进来的题啊QAQ

又没想出网络流解法啊QAQ

看见P是10就又状压了吖QwQ

bfs跑一遍就吼了w

为啥子网络流24题总是状压+最短路/bfs啊QAQ

哦对记得门和墙要建双向边[哭晕]

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;

struct node
{
	int x,key;
	node(){}
	node(int _x,int _key){x=_x,key=_key;}
};
int dis[101][1124],n,m,key[111],in[111],p;bool vis[111][1124];
queue<node> que;
int id(int x,int y)// 0~n*m-1
{
	return (x-1)*m+y-1;
}
struct edge{int to,lt,lim;}e[1111];int cnt;
void addedge(int x1,int y1,int x2,int y2,int lim)
{
	e[++cnt].to=id(x2,y2);e[cnt].lt=in[id(x1,y1)];
	e[cnt].lim=lim;in[id(x1,y1)]=cnt;
}
int ans=2002122500;
void dij()
{
	//int x,y,tmp;
	int tmp;
	memset(dis,48,sizeof(dis));
	memset(vis,0,sizeof(vis));
	dis[0][key[0]]=0;que.push(node(0,key[0]));
	while(!que.empty())
	{
		node cur=que.front();que.pop();
		if(vis[cur.x][cur.key])	continue;
		vis[cur.x][cur.key]=1;
		//printf("QAQ");
		tmp=dis[cur.x][cur.key];
		if(cur.x==n*m-1)	ans=min(ans,tmp);
		//int x=cur.x/m+1,y=cur.x%m+1;
		for(int i=in[cur.x];i;i=e[i].lt)
		{
			if((e[i].lim&cur.key)!=e[i].lim)	continue;
			if(!vis[e[i].to][cur.key|key[e[i].to]])
			{
				//printf("*%d %d %d %d %d -> %d %d %d %d\n",e[i].lim,x,y,cur.key,tmp,e[i].to/m+1,e[i].to%m+1,cur.key|key[e[i].to],tmp+1);;
				dis[e[i].to][cur.key|key[e[i].to]]=tmp+1;
				que.push(node(e[i].to,cur.key|key[e[i].to]));
			}
		}
	}
}
bool door[11][11][11][11];
int main()
{
	int k,i,x1,y1,x2,y2,kk,g,x,y;
	//printf("%d\n",-1&3);
	scanf("%d%d%d",&n,&m,&p);
	scanf("%d",&k);
	for(i=1;i<=k;i++)
	{
		scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&g);
		door[x1][y1][x2][y2]=1;door[x2][y2][x1][y1]=1;
		//printf("%d %d %d %d %d\n",x1,y2,x2,y2,g);
		if(!g)	addedge(x1,y1,x2,y2,-1),addedge(x2,y2,x1,y1,-1);
		else	addedge(x1,y1,x2,y2,1<<(g-1)),addedge(x2,y2,x1,y1,1<<(g-1));
	}
	for(x=1;x<=n;x++)
	{
		for(y=1;y<=m;y++)
		{
			if(x>1&&!door[x][y][x-1][y])	addedge(x,y,x-1,y,0);
			if(y>1&&!door[x][y][x][y-1])	addedge(x,y,x,y-1,0);
			if(x<n&&!door[x][y][x+1][y])	addedge(x,y,x+1,y,0);
			if(y<m&&!door[x][y][x][y+1])	addedge(x,y,x,y+1,0);
		}
	}
	scanf("%d",&g);
	for(i=1;i<=g;i++)
	{
		scanf("%d%d%d",&x,&y,&kk);
		key[id(x,y)]|=(1<<kk-1);
	}
	dij();
	if(ans==2002122500)printf("-1\n");
	else	printf("%d\n",ans);
	return 0;
}

 

转载于:https://www.cnblogs.com/hanyuweining/p/10321959.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值