• 埃雷萨拉斯寻宝【最短路】


    题目大意:

    题目链接:http://10.156.31.134/contestnew.aspx?cid=123 (学校局域网)

    从第一行任一格子出发,到最后一行任一格子,可以传送到相同的魔法格里,经过不同的魔法格会损伤不同的生命(如果之前经过过就不会)。求最大剩余生命。


    思路:

    显然最短路啊。

    因为同一个魔法格内可以互相传送,所以就按照魔法格的点权建点。
    把每一个点拆成入点和出点,之间连长度为这个点损耗的生命值的边。
    接下来,如果点xxyy有相邻,那么在这两个点分别相连。
    然后跑一边dijdij就可以了。


    代码:

    #include <queue>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #define mp make_pair
    using namespace std;
    
    const int N=2510;
    int n,m,hp,ans,tot,head[N+N],dis[N+N],map[N][N];
    bool used[N][N],vis[N+N];
    
    struct edge
    {
    	int dis,next,to;
    }e[N*N*4+N];
    
    int read()
    {
    	int d=0;
    	char ch=getchar();
    	while (!isdigit(ch)) ch=getchar();
    	while (isdigit(ch))
    		d=(d<<3)+(d<<1)+ch-48,ch=getchar();
    	return d;
    }
    
    void add(int from,int to,int dis)
    {
    	e[++tot].to=to;
    	e[tot].dis=dis;
    	e[tot].next=head[from];
    	head[from]=tot;
    }
    
    void dij()
    {
    	memset(dis,0x3f3f3f3f,sizeof(dis));
    	priority_queue<pair<int,int> > q;
    	for (int i=1;i<=n;i++)
        	if (!vis[map[1][i]])
        	{
        		vis[map[1][i]]=1;
        		q.push(mp(0,map[1][i]));
        		dis[map[1][i]]=0;
        	}
        memset(vis,0,sizeof(vis));
        while (q.size())
        {
            int u=q.top().second,v;
            q.pop();
            if (vis[u]) continue;
            vis[u]=1;
            for (int i=head[u];~i;i=e[i].next)
            {
                v=e[i].to;
                if (dis[v]>dis[u]+e[i].dis)
                {
                    dis[v]=dis[u]+e[i].dis;
                    q.push(mp(-dis[v],v));
                }
            }
        }
    }
    
    int main()
    {
    	freopen("data.txt","r",stdin);
    	memset(head,-1,sizeof(head));
    	n=read(),m=read(),hp=read();
    	for (int i=1;i<=m;i++)
    		add(i,i+m,read());
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=n;j++)
    			map[i][j]=read();
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=n;j++)
    		{
    			if (i>1&&!used[map[i][j]][map[i-1][j]])	add(map[i][j]+m,map[i-1][j],0),used[map[i][j]][map[i-1][j]]=1;
    			if (i<n&&!used[map[i][j]][map[i+1][j]])	add(map[i][j]+m,map[i+1][j],0),used[map[i][j]][map[i+1][j]]=1;
    			if (j>1&&!used[map[i][j]][map[i][j-1]])	add(map[i][j]+m,map[i][j-1],0),used[map[i][j]][map[i][j-1]]=1;
    			if (j<m&&!used[map[i][j]][map[i][j+1]])	add(map[i][j]+m,map[i][j+1],0),used[map[i][j]][map[i][j+1]]=1;
    		}
    	dij();
    	ans=1e9;
    	for (int i=1;i<=n;i++)
    		if (dis[map[n][i]+m]<ans) ans=dis[map[n][i]+m];
    	if (ans<hp) printf("%d",hp-ans);
    		else printf("NO");
    	return 0;
    }
    
  • 相关阅读:
    C++日记 OPENGL错误及解决方案
    C++日记 VS编译问题
    OpenGL 自制API 4
    C++日记 宏定义函数
    OpenGL 自制API gluPerspective
    OpenGL 自制API 3
    OpenGL 自制API 2
    OpenGL 自制API 1
    OPENGL入门教程
    c++基础的记录(随笔记录一些基础的东西)
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998215.html
Copyright © 2020-2023  润新知