• 【YBTOJ】【Luogu P6474】[NOI Online #2 入门组] 荆轲刺秦王


    链接:

    题目

    题目大意:

    从起点 (S) 到终点 (T),一个单位时间可以向八个方向走一步或上下左右四个方向走 (d) 步并消耗一个瞬移次数,卫兵格子走不了,特殊格子要消耗一个隐形次数才能走。求最优的情况。

    正文:

    本题难就难在,怎么快速地搞定这个特殊格子。我们只要用差分就好了。

    然后便是用 BFS 做迷宫问题。

    代码:

    int n, m, c1, c2, d, tx, ty;
    
    int dx[9] = {0, 1, -1, 0, 0, 1, -1, 1, -1},
    	dy[9] = {0, 0, 0, 1, -1, 1, -1, -1, 1};
    
    struct node
    {
    	int x, y, c1, c2, stp; 
    }ans;
    
    queue <node> que;                                   
    int vis[N][N]; // >=0 - enemy, -2 - visited, -3 - invisibility, -1 - free
    bool visi[N][N][20][20];
    
    bool bfs ()
    {
    	while (!que.empty())
    	{
    		node b = que.front(); que.pop();
    		if (b.stp > ans.stp) continue;
    		if (b.x == tx && b.y == ty)
    		{
    			if (ans.stp != b.stp) ans = ans.stp < b.stp? ans: b;
    			else
    			{
    				if (ans.c1 + ans.c2 != b.c1 + b.c2) 
    					ans = ans.c1 + ans.c2 < b.c1 + b.c2? ans: b;
    				else
    					ans = ans.c1 < b.c1? ans: b;
    			}
    			continue;
    		}
    		
    		for (int i = 1; i <= 8; i++)
    		{
    			int x = b.x + dx[i], y = b.y + dy[i];
    			if (vis[x][y] >= 0) continue;
    			if (vis[x][y] == -3)
    			{
    				if (x < 0 || x > n || y < 0 || y > m) continue;
    				if (b.c1 + 1 > c1 || visi[x][y][b.c1 + 1][b.c2]) continue;
    				visi[x][y][b.c1 + 1][b.c2] = 1;
    				que.push((node){x, y, b.c1 + 1, b.c2, b.stp + 1});
    			}
    			else
    				if(!visi[x][y][b.c1][b.c2]) que.push((node){x, y, b.c1, b.c2, b.stp + 1}),
    					visi[x][y][b.c1][b.c2] = 1; 
    		}
    		if (b.c2 + 1 > c2) continue;
    		for (int i = 1; i <= 4; i++)
    		{
    			int x = b.x + dx[i] * d, y = b.y + dy[i] * d;
    			if (x < 0 || x > n || y < 0 || y > m) continue;
    			if (vis[x][y] >= 0) continue;
    			if (vis[x][y] == -3)
    			{
    				if (b.c1 + 1 > c1 || visi[x][y][b.c1 + 1][b.c2 + 1]) continue;
    				visi[x][y][b.c1 + 1][b.c2 + 1] = 1;
    				que.push((node){x, y, b.c1 + 1, b.c2 + 1, b.stp + 1});
    			}
    			else
    				if(!visi[x][y][b.c1][b.c2 + 1]) que.push((node){x, y, b.c1, b.c2 + 1, b.stp + 1}),
    					visi[x][y][b.c1][b.c2 + 1] = 1; 
    		}
    	}
    } 
    
    int tag[N][N];
    
    void Tag(int x, int y, int k)
    {
    	for (int i = 0; i <= k; i++)
    	{
    		tag[max(x - i, 1)][max(y - k + i, 1)]++;
    		tag[max(x - i, 1)][min(y + k - i, m) + 1]--;
    		
    		tag[max(x + i, 1)][max(y - k + i, 1)]++;
    		tag[max(x + i, 1)][min(y + k - i, m) + 1]--;
    	}
    }
    
    int main()
    {
    //	freopen("bandit18.in", "r", stdin);
    	ans = (node){0, 0, 1e9, 1e9, 1e9}; 
    	scanf ("%d%d%d%d%d", &n, &m, &c1, &c2, &d);
    	memset (vis, 0, sizeof vis);
    	for (int i = 1; i <= n; i++)
    	{
    		char c;
    		for (int j = 1; j <= m; j++)
    		{
    			c = getchar();
    			while (c != 'S' && c != 'T' && c != '.' && !(c >= '0' && c <= '9')) c = getchar();
    			int x = 0;
    			if (c == 'S') {que.push((node){i, j, 0, 0, 0});visi[i][j][0][0] = 1;continue;} 
    			if (c == '.') {vis[i][j] = -1;continue;} 
    			if (c == 'T') {tx = i, ty = j, vis[i][j] = -1;continue;} 
    			
    			while (c >= '0' && c <= '9') 
    				x = x * 10 + c - '0', c = getchar();
    			vis[i][j] = x;
    			Tag(i, j, x - 1);
    		}
    	}
    	for (int i = 1; i <= n; i++)
    	{
    		int sum = 0;
    		for (int j = 1; j <= m; j++)
    		{
    			sum += tag[i][j];
    			if (sum && vis[i][j] < 1) vis[i][j] = -3;
    		}
    	}
    	bfs();
    	if(ans.stp == 1e9) puts("-1");
    	else printf("%d %d %d
    ", ans.stp, ans.c1, ans.c2);
    	return 0;
    }
    
  • 相关阅读:
    201521123121 《Java程序设计》第9周学习总结
    201521123121 《JAVA程序设计》第8周学习总结
    201521123121 《JAVA程序设计》第7周学习总结
    201521123121 《JAVA程序设计》第6周学习总结
    201521123121 《Java程序设计》第5周学习总结
    201521123121 《Java程序设计》第4周学习总结
    201521123121 《Java程序设计》第3周学习总结
    201521123118《java程序与设计》第11周学习总结
    201521123118《java程序与设计》第10周学习总结
    201521123118《java程序与设计》第8周学习总结
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14313053.html
Copyright © 2020-2023  润新知