• 【JZOJ 5459】密室【最短路】


    题目大意:

    题目链接:https://jzoj.net/senior/#main/show/5459
    题目图片:
    http://wx1.sinaimg.cn/mw690/0060lm7Tly1fva78gse8vj30jc0fu3z6.jpg
    http://wx2.sinaimg.cn/mw690/0060lm7Tly1fva78grjjuj30jb072t8m.jpg
    http://wx1.sinaimg.cn/mw690/0060lm7Tly1fva78gsbd8j30hk0c1aa8.jpg
    给出一个有向图,走一条边需要一些钥匙,只有拥有这些钥匙才可以走,走完后钥匙不会消失。到达点可以获得在这个点上的钥匙。求从11nn的最短路。(边权均为1)


    思路:

    终于找到一道SPFASPFA的变形的题目了。。。
    这道题在普通SPFASPFA的基础上增加了条件,如果能处理好这些条件,那么就是一个裸的SPFASPFA
    我们可以用状态压缩储存每个点有的钥匙和每条路需要的钥匙,每条路需要的钥匙可以直接在结构体里面加上一维e[i].keye[i].key
    然后再跑SPFASPFA的时候,再加上一个队列keynumkeynumkeynumkeynum的每一位应该和qq的每一位两两对应。keynumkeynum储存的是到达这个状态的时候的钥匙压缩后的数字
    那么当我们决定要走这条路的时候,除了SPFASPFA本身的距离判断,还要再加上一个现在拥有的钥匙是否可以走这条路的判断。我们知道,如果可以走这条路,那么就必须拥有开启这条路的钥匙,所以就有num&e[i].key=e[i].keynum\&e[i].key=e[i].k ey
    最后枚举到达终点时的钥匙,并输出最小值即可。


    代码:

    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <map>
    #define N 6100
    #define Inf 1e9
    using namespace std;
    
    int n,m,k,tot,key[N],head[N],dis[N][1024],x,y,z;
    bool vis[N][1024];
    
    struct edge
    {
    	int next,to,key;
    }e[N];
    
    void add(int from,int to,int num)
    {
    	tot++;
    	e[tot].to=to;
    	e[tot].key=num;
    	e[tot].next=head[from];
    	head[from]=tot;
    }
    
    void spfa()
    {
    	memset(vis,0,sizeof(vis));
    	memset(dis,0x3f3f3f3f,sizeof(dis));
    	vis[1][key[1]]=1;
    	dis[1][key[1]]=0;  //第二维表示到达这个点时钥匙压缩后的数字
    	queue<int> q;
    	queue<int> keynum;
    	q.push(1);
    	keynum.push(key[1]);
    	while (q.size())
    	{
    		int num=keynum.front();
    		keynum.pop();
    		int u=q.front();
    		q.pop();
    		vis[u][num]=0;
    		for (int i=head[u];~i;i=e[i].next)
    		{
    			int v=e[i].to;
    			if (((num&e[i].key)==e[i].key)&&(dis[v][num|key[v]]>dis[u][num]+1))  //num|key[v]是到达v点之后的钥匙数量
    			{
    				dis[v][num|key[v]]=dis[u][num]+1;
    				if (!vis[v][num|key[v]])
    				{
    					vis[v][num|key[v]]=1;
    					q.push(v);
    					keynum.push(num|key[v]);
    				}
    			}
    		}
    	}
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d%d%d",&n,&m,&k);
    	for (int i=1;i<=n;i++)
    	 for (int j=k;j>=1;j--)
    	 {
    	 	scanf("%d",&x);
    	 	if (x) key[i]+=(1<<(j-1));
    	 }
    	for (int i=1;i<=m;i++)
    	{
    		scanf("%d%d",&x,&y);
    		int num=0;
    		for (int j=k;j>=1;j--)
    		{
    			scanf("%d",&z);
    			if (z) num+=(1<<(j-1));
    		} 
    		add(x,y,num);
    	}
    	spfa();
    	int ans=Inf;
    	for (int i=0;i<=1023;i++)
    	 ans=min(ans,dis[n][i]);
    	if (ans<Inf) printf("%d\n",ans);
    	 else printf("No Solution");
    	return 0;
    }
    
  • 相关阅读:
    互联网行业加班排行榜第一!
    那些年我们一起优化的SQL
    我变强了
    同事吵架一时爽,事后两行泪!
    腾讯公布 23 年前第一间办公室照片,太有年代感了
    接口用例自动回归实践
    寻找终身事业,而非升职加薪
    从功能测试进阶自动化测试,熬夜7天整理出这一份3000字超全学习指南
    智能测试的三个阶段
    测试妹子说我代码有坑,我直接翻脸!
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998586.html
Copyright © 2020-2023  润新知