当前位置:网站首页>leetcode——启发式搜索
leetcode——启发式搜索
2022-04-23 04:49:00 【csdn_ggboy】
847. 访问所有节点的最短路径 - 力扣(LeetCode)
一个很重要的优化,起点一定是连接节点个数最少的,这样保证了路径最短
class Solution
{
public:
struct state
{
int now;
int loc;
int dist; //这是比较用的dist,dis + astar
//返回值是bool类型,重载运算符<, 右边参数为不能修改的引用,这个函数不会修改结构体的值
bool operator<(const state &rhs) const
{
return dist > rhs.dist;
}
};
int astar(int loc)
{
// 1的数量表示还需要去哪些点
int res = 0;
while (loc)
{
loc -= (loc & -loc);
res++;
}
return res;
}
int shortestPathLength(vector<vector<int>> &graph)
{
int n = graph.size();
int ans = 0x3f3f3f3f;
int mi = 0x3f3f3f3f;
for(auto &p: graph)
mi=min(mi, (int)p.size());
unordered_map<int, unordered_map<int, int>> dist;
priority_queue<state, vector<state>> q;
for (int i = 0; i < n; i++)
{
//起点i
if(graph[i].size() != mi) continue;
int loc = ((1 << n) - 1) ^ (1 << i);
dist[i][loc] = 0;
q.push({
i, loc, n - 1});
}
while (q.size())
{
auto t = q.top();
q.pop();
int u = t.now;
int d = astar(t.loc);
if(d > astar(t.loc) + dist[u][t.loc]) continue;
if (astar(t.loc) == 0)
{
ans = min(ans, t.dist);
break;
}
for (int j = 0; j < graph[u].size(); j++)
{
int nx = graph[u][j];
int nloc = t.loc;
if (t.loc & (1 << nx))
nloc ^= (1 << nx);
//如果nx位置没有走过,更新nloc
// if(st[nx][nloc]) continue;
if (!dist.count(nx) || !dist[nx].count(t.loc) || dist[nx][nloc] > dist[u][t.loc] + 1)
{
dist[nx][nloc] = dist[u][t.loc] + 1;
q.push({
nx, nloc, dist[nx][nloc] + astar(nloc)});
}
}
}
return ans;
}
};
127. 单词接龙 - 力扣(LeetCode)
class Solution
{
public:
typedef pair<int,int> PII;
bool edgeif(string a, string b)
{
unordered_map<char, int> mp;
if (a == b)
return true;
bool flag = false;
for (int i = 0; i < a.size(); i++)
{
if (a[i] != b[i] && !flag)
{
flag = true;
}
else if(a[i] != b[i] && flag)
return false;
}
return true;
}
int astar(int _a, int _end, vector<string> &wordList)
{
string a = wordList[_a];
string end = wordList[_end];
if (a.size() != end.size())
return 0x3f3f3f3f;
int res = 0;
for (int i = 0; i < a.size(); i++)
{
if (a[i] != end[i])
res++;
}
return res;
}
int ladderLength(string beginWord, string endWord, vector<string> &wordList)
{
wordList.push_back(beginWord);
if (find(wordList.begin(), wordList.end(), endWord) == wordList.end())
return 0;
wordList.push_back(endWord);
int n = wordList.size();
unordered_map<string, int> mp;
for(int i = 0; i < wordList.size(); i ++) mp[wordList[i]] = i;
int dist[n];
bool st[n];
memset(dist, 0x3f3f3f3f, sizeof(dist));
memset(st, 0, sizeof(st));
dist[n - 2] = 0;
st[n - 2] = true;
priority_queue<PII, vector<PII>, greater<PII>> q;
q.push({
astar(n - 2, n - 1, wordList), n - 2});
while (q.size())
{
auto t = q.top();
q.pop();
int u = t.second;
if(u == n - 1) break;
st[u] = false;
for(int i = 0; i < 26; i ++ )
for(int j = 0; j < wordList[u].size(); j ++)
{
string now = wordList[u];
if(now[j] != 'a' + i)
{
now[j] = 'a' + i;
}
if(!mp.count(now))
continue;
int to = mp[now];
if (st[to])
continue;
int d_a = astar(to, n - 1, wordList);
if (dist[to] > dist[u] + 1 )
{
dist[to] = dist[u] + 1;
st[to] = true;
q.push({
dist[to] + d_a, to});
}
}
}
if (dist[n - 1] >= 0x3f3f3f3f)
return 0;
return dist[n - 1] + 1;
}
};
752. 打开转盘锁 - 力扣(LeetCode)
class Solution
{
public:
// 0 1 2 3 4 5 6 7 8 9
typedef pair<int, string> PIS;
int astar(string a, string target)
{
int res = 0;
for (int i = 0; i < a.size(); i++)
{
res += min((a[i] - target[i] + 10) % 10, (-a[i] + target[i] + 10) % 10);
}
return res;
}
int openLock(vector<string> &deadends, string target)
{
if(target == "0000") return 0;
//每个数字可以有两个旋转方式,每次可以选择一个位置旋转,不能旋转到死亡数字
priority_queue<PIS, vector<PIS>, greater<PIS>> q;
unordered_map<string, bool> st;
unordered_map<string, int> dist;
for (auto p : deadends)
st[p] = true; //标记死亡状态
if (!st["0000"])
{
q.push({
astar("0000", target), "0000"}); //初始状态
st["0000"] = true;
}
bool flag = false;
while (!q.empty())
{
auto u = q.top();
string t = u.second;
st[t] = false;
q.pop();
if (t == target)
{
break;
}
for (int i = 0; i < 4; i++) //找一个位置
{
string ne = t;
ne[i] = (t[i] - '0' + 1) % 10 + '0';
if (!st[ne])
{
if (!dist.count(ne) || dist[ne] > dist[t] + 1)
{
dist[ne] = dist[t] + 1;
st[ne] = true;
q.push({
dist[ne] + astar(ne, target), ne});
}
}
ne[i] = (t[i] - '0' - 1 + 10) % 10 + '0';
if (!st[ne])
{
if (!dist.count(ne) || dist[ne] > dist[t] + 1)
{
dist[ne] = dist[t] + 1;
st[ne] = true;
q.push({
dist[ne] + astar(ne, target), ne});
}
}
}
}
if (dist.count(target))
return dist[target];
else
return -1;
}
};
773. 滑动谜题 - 力扣(LeetCode)
#define x first
#define y second
class Solution {
public:
string end = "123450";
int dx[4] = {
0, 0, 1, -1}, dy[4] = {
1, -1, 0, 0};
typedef pair<int, string> PIS;
int f(string s)
{
int res = 0;
for(int i = 0; i < s.size(); i ++ )
if(s[i] != '0')
{
int p = s[i] - '1';
res += abs(i / 3 - p / 3) + abs(i % 3 - p % 3);
}
return res;
}
int bfs(string state)
{
unordered_map <string, int> dist;
priority_queue <PIS, vector<PIS>, greater<PIS>> q;
unordered_map <string, bool> st;
st[state] = true;
q.push({
f(state), state});//将初始状态入栈
dist[state] = 0;
while(q.size())
{
auto t = q.top();
q.pop();
string s = t.y;
if(s == end) break;
st[s] = false;
int x, y;
for(int i = 0; i < 6; i ++ )//找到0的位置
{
if(s[i] == '0')
{
x = i / 3;
y = i % 3;
break;
}
}
for(int i = 0; i < 4; i ++ )//和上下左右交换
{
int nx = x + dx[i], ny = y + dy[i];
if(nx < 0 || ny < 0 || nx > 1 || ny > 2) continue;//两行三列
string source = s;
swap(source[x * 3 + y], source[nx * 3 + ny]);
if(st[source]) continue;
if(!dist.count(source) || dist[source] > dist[s] + 1)//dist是无穷大或者是比s + 1大
{
dist[source] = dist[s] + 1;
q.push({
f(source) + dist[source], source});
}
}
}
return dist[end];
}
int slidingPuzzle(vector<vector<int>>& board) {
//A* 多次入栈,终点出栈只能确定终点的最短路径
//判断是否有解
string start;
for(auto &t : board)
for(auto &x : t)
start += x + '0';
int cnt = 0;
for(int i = 0; i < 6; i ++ )
for(int j = i + 1; j < 6; j ++ )
{
if(start[i] != '0' && start[j] != '0' && start[j] < start[i]) cnt ++;
}
if(cnt % 2) return -1;
else return bfs(start);
}
};
版权声明
本文为[csdn_ggboy]所创,转载请带上原文链接,感谢
https://blog.csdn.net/csdn_ggboy/article/details/124291327
边栏推荐
- Learning Android II from scratch - activity
- List&lt; Map&gt; Replication: light copy and deep copy
- The programmer starts the required application with one click of window bat
- DIY 一个 Excel 版的子网计算器
- Recommended scheme of national manufactured electronic components for intelligent electronic scales
- Spark small case - RDD, spark SQL
- Recommended scheme of national manufactured electronic components
- Innovation training (10)
- Com alibaba. Common methods of fastjson
- Record the blind injection script
猜你喜欢

Unity RawImage背景无缝连接移动

Recommended scheme for national production of electronic components of wireless keyboard

Youqilin 22.04 lts version officially released | ukui 3.1 opens a new experience

Excel uses the functions of replacement, sorting and filling to comprehensively sort out financial data

Spark small case - RDD, spark SQL

PIP3 installation requests Library - the most complete pit sorting

Record the ThreadPoolExecutor main thread waiting for sub threads

AWS eks add cluster user or Iam role

Recommended scheme of national manufactured electronic components for intelligent electronic scales

MySQL -- execution process and principle of a statement
随机推荐
Installation and deployment of Flink and wordcount test
Implementation of switching windows and capturing data in selenium mode
L2-011 玩转二叉树(建树+BFS)
PHP 统计指定文件夹下文件的数量
Kotlin. The binary version of its metadata is 1.6.0, expected version is 1.1.15.
C language: spoof games
敏捷实践 | 提高小组可预测性的敏捷指标
Sword finger offer: push in and pop-up sequence of stack
Teach you how to build the ruoyi system by Tencent cloud
Simply drag objects to the item bar
Record the ThreadPoolExecutor main thread waiting for sub threads
Innovation training (V) mid term inspection
Mysql50 basic exercises
List remove an element
Spark small case - RDD, broadcast
Create VPC in AWS console (no plate)
C list field sorting contains numbers and characters
The last day of 2021 is the year of harvest.
Pixel 5 5g unlocking tutorial (including unlocking BL, installing edxposed and root)
io. Platform. packageRoot; // ignore: deprecated_ Member_ use