• 7139 Dragon slayer


    题目描述:
    Long, long ago, the dragon captured the princess. In order to save the princess, the hero entered the dragon’s lair.

    The dragon’s lair is a rectangle area of length n and width m. The lower left corner is (0,0) and the upper right corner is (n,m).

    The position of the hero is (xs+0.5,ys+0.5).

    The position of the dragon is (xt+0.5,yt+0.5).

    There are some horizontal or vertical walls in the area. The hero can move in any direction within the area, but cannot pass through walls, including the ends of walls.

    The hero wants to go where the dragon is, but may be blocked by walls.

    Fortunately, heroes have access to special abilities, and each use of a special ability can make a wall disappear forever.

    Since using special abilities requires a lot of physical strength, the hero wants to know how many times special abilities need to be used at least on the premise of being able to reach the position of the evil dragon?

    Input
    The first line contains an integer T(T≤10) —the number of test cases.

    The first line of each test case contains 3 integers n,m,K(1≤n,m,K≤15) —length and width of rectangular area, number of walls

    The second line of each test case contains 4 integers xs,ys,xt,yt(0≤xs,xt

    The next K lines , each line contains 4 integers x1,y1,x2,y2(0≤x1,x2≤n,0≤y1,y2≤m) — indicates the location of the two endpoints of the wall, ensuring that x1=x2 or y1=y2.

    Output
    For each test case, a line of output contains an integer representing at least the number of times the special ability was required.

    Sample Input

    2
    3 2 2 
    0 0 2 1
    0 1 3 1
    1 0 1 2
    3 2 2 
    0 0 2 1
    2 1 2 2
    1 0 1 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Sample Output

    2
    0
    
    • 1
    • 2

    思路:
    最开始想复杂了,以为是最短路用双端队列做的,后来发现穿过一堵墙之后墙会永远消失,这个条件不好用最短路来判断。
    下面用爆搜做的。
    一个细节,用位运算记录搜索状态。
    例如:共有k个条件,可以选择是否使用,那么就有 2 k 2^k 2k个状态。
    此时可以用for(int i=0;i<(1<遍历每个状态。
    若要检测这个状态中是否有第j个条件,则可以用(j<<1)&&i来检测。j从0开始标号。
    本题枚举每种墙的组合,针对某一种墙的组合,从起点开始广搜,若遇到墙,则无法通过。
    比较每一种能到达终点的状态所存在的墙的数量,数量最大的状态即为本题的答案状态。
    因为其存在的墙数最多,即剩余的墙的数量最多,即去掉的墙的数量最少,那么答案就是总墙数减去此状态下墙的数量。
    代码:

    #include
    #include
    #include
    #include
    using namespace std;
    typedef pair<int, int>PII;
    using namespace std;
    const int N = 1e6 + 10;
    int dx[4] = { 1,-1,0,0 }, dy[4] = {0,0,-1,1};
    struct edge
    {
    	int x1, y1, x2, y2;
    }w[N];
    bool st[20][20];
    int main()
    {
    	int T;
    	cin >> T;
    	while (T--)
    	{
    		int n, m, k;
    		cin >> n >> m >> k;
    		int x1, y1, x2, y2;
    		cin >> x1 >> y1 >> x2 >> y2;
    		
    		for (int i = 1; i <= k; i++)
    		{
    			int a, b, c, d;
    			cin >> a >> b >> c >> d;
    			w[i] = {a,b,c,d};
    		}
    
    		int cnt = 0;
    		int res = -1;
    		for (int i = 0; i < (1 << k); i++)
    		{
    			cnt = 0;
    			memset(st, false, sizeof st);
    			vector<PII>heng[20];
    			vector<PII>shu[20];
    			for (int j = 0; j < k; j++)
    			{
    				if ((1 << j) & i)
    				{
    					cnt++;
    					int a = w[j+1].x1;
    					int b = w[j+1].y1;
    					int c = w[j+1].x2;
    					int d = w[j+1].y2;
    					if (a == c) // 横边
    					{
    						heng[a].push_back({min(b, d), max(b, d)});
    					}
    					if (b == d) // 竖边
    					{
    						shu[b].push_back({min(a, c), max(a, c)});
    					}
    				}
    			}
    			bool flag = false;
    			queue<PII>q;
    			q.push({x1,y1});
    			st[x1][y1] = true;
    			while (!q.empty())
    			{
    				PII pos = q.front();
    				q.pop();
    				if (pos.first == x2 && pos.second == y2)
    				{
    					flag = true;
    					break;
    				}
    				for (int i = 0; i < 4; i++)
    				{
    					int a = pos.first + dx[i];
    					int b = pos.second + dy[i];
    					if (a < 0 || a >= n || b < 0 || b >= m)
    					{
    						continue;
    					}
    					if (st[a][b])
    					{
    						continue;
    					}
    					bool qiang = false; // 是否有墙
    					if (a == pos.first) // 横着走
    					{
    						int yy = max(b, pos.second);
    						if (!shu[yy].empty())
    						{
    							for (auto p : shu[yy])
    							{
    								int l = p.first;
    								int r = p.second;
    								if (l <= a && r > a)
    								{
    									qiang = true;
    									break;
    								}
    							}
    						}
    					}
    
    					if (b == pos.second) // 竖着走
    					{
    						int xx = max(a, pos.first);
    						if (!heng[xx].empty())
    						{
    							for (auto p : heng[xx])
    							{
    								int l = p.first;
    								int r = p.second;
    								if (l <= b && b < r)
    								{
    									qiang = true;
    									break;
    								}
    							}
    						}
    					}
    
    					if (qiang)
    					{
    						continue;
    					}
    
    					q.push({a,b});
    					st[a][b] = true;
    				}
    			}
    			if (flag)
    			{
    				res = max(res, cnt);
    			}
    		}
    		if (res == -1) cout << -1 << endl;
    		else cout << k - res << endl;   //结果
    		
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
  • 相关阅读:
    mac删除带锁标识的app
    面向对象重写理解 求值策略 -共享对象调用 面向对象原则
    C# 连接Mysql数据库查询结果显示在datagridview控件上 采用ADO.NET模式
    JavaScript基础 JavaScript第二天 2. 语句
    【LeetCode】35.复杂链表的复制
    基于遗传算法的大规模电动汽车充电行为优化
    压缩软件的效率和实例比较 zip, gz, rar, 7z,数据库备份
    云原生可观测框架 OpenTelemetry 基础知识(架构/分布式追踪/指标/日志/采样/收集器)
    使用gitlab的cicd自动化部署vue项目shell流程踩坑之路
    [附源码]Python计算机毕业设计Django兴达五金日杂批发商店管理系统
  • 原文地址:https://blog.csdn.net/weixin_50616227/article/details/125890335