IDEA插件系列(47):LongTimeToDate插件——日期转换

彻底搞懂HTTP

  返回  

1495 孤岛营救问题

2021/8/21 11:30:11 浏览:

1495 孤岛营救问题

这个题是一个历史题加阅读理解题

数学是火,点亮物理的灯。物理是灯,照亮化学的路。化学是路,通向生物的坑。生物是坑,埋葬了理科生,

很明显是一个最短路径的问题,好模板,要是开始也能遇见这么模板的题就好了
然后就是这个题可以用两种做法,一个是最短路版本,一个广度优先搜索版本

广搜

广搜,这个版做法其实就是把每个状态的钥匙进行分层,然后根据状态进行搜索最短路径

#include<bits/stdc++.h>
using namespace std;
const int N = 12;
int dir[5][3]={{0,1},{1,0},{0,-1},{-1,0}};//方位数组
int e[N][N][N][N],key[N][N][N],dkey[N][N];
int vis[N][N][1<<14];
int n,m;
struct node{
	int x,y,k,d;
	node(){}
	node(int x,int y,int k,int d):x(x),y(y),k(k),d(d){}
};
int getkey(int x,int y){
	int ans = 0;
	for(int i=1;i<=dkey[x][y];i++)
	ans|=(1<<(key[x][y][i]-1));//计算钥匙和
	return ans;
}
int bfs(){
	queue<node> q;
	int sk = getkey(1,1);
	q.push(node(1,1,sk,0)),vis[1][1][sk] = 1;
	while(q.size()){
		node u = q.front();q.pop();
		if(u.x==n && u.y==m) return u.d;
		int ux = u.x,uy = u.y;
		for(int i=0;i<4;i++){
			int nx = ux+dir[i][0];
			int ny = uy+dir[i][1];
			int opt = e[ux][uy][nx][ny];//取队头进行操作
			if(nx <1||ny<1||nx>n||ny>m||opt<0||(opt&&!(u.k&(1<<(opt-1))))) continue;
			int nkey = u.k|getkey(nx,ny);
			if(vis[nx][ny][nkey]) continue;//已经访问了
			q.push(node(nx,ny,nkey,u.d+1));
			vis[nx][ny][nkey] = 1;//标记访问
		}
	}
	return -1;
}
void read(){
	int k,s,r;
	scanf("%d%d%d",&n,&m,&r);
	for(scanf("%d",&k);k--;){
		int x1,y1,x2,y2,g;
        scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&g);
        if(g) e[x1][y1][x2][y2]=e[x2][y2][x1][y1]=g;//存储路径
        else e[x1][y1][x2][y2]=e[x2][y2][x1][y1]=-1;//无路径到达
	}
   for(scanf("%d",&s);s--;) {
        int x,y,q;
        scanf("%d%d%d",&x,&y,&q);
        key[x][y][++dkey[x][y]]=q;//存储钥匙
    }
} 
int main(){
	read();
    printf("%d\n",bfs());
	return 0;
} 

最短路

这里涉及到的东西有很多,我们还要计算出最多的边数1>>101010=1024000


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
const int N = 12;
const int M = 1024100;
const int INF = 0x3f3f3f3f;
typedef pair<int,int> P;
struct keyn
{
	int x,y;
}key[N][20];//key[i][j] 种类为i的钥匙第j把的坐标 
int n,m,p,s,k,cnt,layer,nn,nsum;//n宽,m长,p种类,s总钥匙数,k总障碍数,cnt计数器,layer层数,nn每层的点,nsum总点数 
int num[N][N],fg[200][200];
int head[M],nex[M],ver[M],edge[M];
int hadk[N],kn[N],vis[M],dis[M];
void add(int x,int y,int w)//邻接表存储图
{
	ver[++cnt] = y;
	nex[cnt] = head[x];
	edge[cnt] = w;
	head[x] = cnt;
}
void read()
{
	cnt = 0;
	int x,y;
	scanf("%d%d%d%d",&n,&m,&p,&k);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			num[i][j] = ++cnt;
	for(int i=1,g,u,v;i<=k;i++)
	{
		scanf("%d%d",&x,&y); u = num[x][y];
		scanf("%d%d",&x,&y); v = num[x][y];
		scanf("%d",&g);
		if(g==0) g=-1;
		fg[u][v] = fg[v][u] = g;//存储图
	}
	scanf("%d",&s);
	for(int i = 1,q;i <= s;i++)
	{
		scanf("%d%d%d",&x,&y,&q);
		kn[q]++;
		key[q][kn[q]].x = x;
		key[q][kn[q]].y = y;//存储钥匙
	}
}
void build()
{
	layer = 1<<p;
	nn = n*m;
	nsum = n*m*layer;
	for(int t=0;t<layer;t++)
	{
		for(int i=1;i<=p;i++)
		{
			if(t&(1<<(i-1))) hadk[i] = 1;
			else hadk[i] = 0;
		}
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
			{
				int u = num[i][j],v = num[i][j+1];//向右连边
				if(v && fg[u][v]!=-1) 
				if(fg[u][v]==0 || hadk[fg[u][v]])
				{
					add(t*nn+u,t*nn+v,1);
					add(t*nn+v,t*nn+u,1);
				}
				
				v = num[i+1][j]; //向下连边
				if(v && fg[u][v]!=-1) 
				if(fg[u][v]==0 || hadk[fg[u][v]])
				{
					add(t*nn+u,t*nn+v,1);
					add(t*nn+v,t*nn+u,1);
				}
			}
		for(int i=1;i<=p;i++)
		{
			if(!hadk[i]) //没有钥匙才可以移动状态 
			for(int j=1;j<=kn[i];j++)
			{
				int u = num[key[i][j].x][key[i][j].y];
				add(t*nn+u,( t|(1<<(i-1)) ) *nn+u,0);
			}
		}	
	}
}
void dj()//dijkstra跑最短路
{
	priority_queue<P> q;
	for(int i = 0;i <= nsum; i++) dis[i] = INF;
	q.push(make_pair(0,1)),dis[1] = 0;
	while(q.size())
	{
		int u = q.top().second;q.pop();
		if(vis[u]) continue;
		vis[u] = 1;
		for(int i = head[u];i;i = nex[i]){
			int v = ver[i],w=edge[i];
			if(dis[v] > dis[u] + w){
				dis[v] = dis[u] + w;//更新最短路
				q.push(make_pair(-dis[v],v));
			}
		}
	}
}
void spfa()
{
	queue<int> q;
	for(int i = 0;i <= nsum;i++) dis[i] = INF;
	q.push(1),dis[1] = 0,vis[1] = 1;
	while(q.size())
	{
		int u = q.front(); q.pop();vis[u] = 0;
		for(int i=head[u];i;i = nex[i])
		{
			int v = ver[i],w=edge[i];
			if(dis[v] > dis[u] + w)
			{
				dis[v] = dis[u] + w;
				if(!vis[v]){
					q.push(v),vis[v] = 1;
				}
			}
		}
		
	}
}
void solve()
{
	int ans = INF;
	for(int i =0;i<layer;i++)
	ans = min(ans,dis[i*nn+num[n][m]]);
	if(ans==INF) printf("-1\n");
	else printf("%d\n",ans);
}
int main()
{
	read();
	build();
	dj();
	solve();
	return 0;
} 

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号