• hdu 2757 Ocean Currents(BFS+DFS)


    题意:给你一个图,图上每个点的信息表示该点的水流方向,若下一步走的方向与水流方向一致,则消耗能量为零,否则消耗能量为1,这样,给定起点和终点,问最少消耗的能量。

    分析:比赛的时候,一开始交了一个思路很简单的代码,就是用优先队列实现,主要就是标记点的问题了,因为即使使用优先队列,如果当初将一个状态标记为0和1,那么有可能在后面存在“已访问的状态消耗的能量大于即将到达那个状态所消耗的能量”,这样,就无法保证消耗的能量最少了。所以,初始的时候,将每一个状态消耗的能量初始为无穷大,之后,当遇到到达该状态消耗更少能量的,则压入队列。这样就保证了消耗能量最少的问题了。但是,但我把这份很容易敲完的代码叫上去之后,2986ms,这时间虽然是没有TLE,但也差不多算没过了。

    该怎么去优化呢?

    想了好久,换了一下思路,将代码改了。

    这样的,在每次压入一个点的是,我们可以顺便把与该点消耗能量相同的点(就是按照该状态下的水流方向走的点)压入队列,就能保证是先压入的点消耗的能量最少了,同时也就不需要用优先队列了,标记状态也只需要标记为0和1 就够了。

    那怎么把能量相同点同时也压入队列呢,其实只需要深搜一下就行了。687ms就过了,但是,如果在找出那些点的过程中不用栈去保存,而是用数组的话,可以再快些。

    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<stack>
    using namespace std;
    struct node
    {
    	int x,y,energy;
    };
    bool vis[1001][1001];
    char map[1001][1001];
    int n,m,ans,si,sj,ei,ej;
    int dir[8][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
    stack<node> ST;
    void DFS(node temp)
    {
    	int k=map[temp.x][temp.y]-'0';
    	int i=temp.x+dir[k][0];
    	int j=temp.y+dir[k][1];
    	node cur;
    	if(i<0||i>=n||j<0||j>=m)
    		return;
    	if(!vis[i][j])
    	{
    		vis[i][j]=true;
    		cur.x=i;cur.y=j;
    		cur.energy=temp.energy;
    		if(i==ei-1 && j==ej-1)
    		{
    			ans=temp.energy;
    			return ;
    		}
    		ST.push(cur);
    		DFS(cur);
    	}
    }
    void BFS()
    {
    	queue<node> Q;
    	node f,temp,cur;
    	f.x=si-1;f.y=sj-1;
    	vis[f.x][f.y]=true;
    	f.energy=0;
    	Q.push(f);
    	while(!Q.empty())
    	{
    		temp=Q.front();
    		Q.pop();
    		DFS(temp);
    		while(!ST.empty())
    	    {
    		    Q.push(ST.top());
    		    ST.pop();
    	    }
    		if(ans!=-1)
    			return ;
    		for(int k=0;k<8;k++)
    		{
    			int i=temp.x+dir[k][0];
    			int j=temp.y+dir[k][1];
    			if(k==map[temp.x][temp.y]-'0')
    				continue;
    			if(i<0||i>=n||j<0||j>=m)
    				continue;
    			if(vis[i][j])
    				continue;
    			vis[i][j]=true;
    			if(i==ei-1 && j==ej-1)
    	    	{
    			    ans=temp.energy+1;
    			    return ;
    			}
    			cur.x=i;cur.y=j;cur.energy=temp.energy+1;
    			Q.push(cur);
    		    DFS(cur);
    		    while(!ST.empty())
    	    	{
    			   Q.push(ST.top());
    			   ST.pop();
    		    }
    		    if(ans!=-1)
    		      return ;
    		}
    	}
    }
    int main()
    {
    	int k;
    	while(scanf("%d %d",&n,&m)==2)
    	{
    		for(int i=0;i<n;i++)
    			  scanf("%s",map[i]);
    		scanf("%d",&k);
    		while(k--)
    		{
    			memset(vis,0,sizeof(vis));
    			scanf("%d %d %d %d",&si,&sj,&ei,&ej);
    			if(si==ei&&sj==ej)
    			{
    				printf("0\n");
    				continue;
    			}
    			ans=-1;
    			BFS();
    			printf("%d\n",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    第3周 实践项目2 建设”顺序表“算法库(可参考为模板)
    第3周实践项目3 求集合并集
    【luogu 2529】【SHOI 2001】击鼓传花
    【BZOJ 3270】博物馆
    【BZOJ 2337】XOR和路径
    浅谈期望dp
    【codeforces 24D】Broken Robot
    【POJ 1463】Strategic game
    【POJ 3585】Accumulation Degree
    【luogu 3146/3147】248/262144
  • 原文地址:https://www.cnblogs.com/nanke/p/2277078.html
Copyright © 2020-2023  润新知