哎 调了一上午,仍然t最后一个点,stl队列和数组模拟队列都试了还是不行
希望有大佬能够指点一下优化方法不胜感激
#include<iostream>
#include<algorithm>
#include<cstring>
#include<unordered_map>
#include<string>
#include<queue>
const int N=200010;
using namespace std;
int n;
/* STL队列调用函数
int extend(queue<string> &qa,unordered_map<string,int> &da,unordered_map<string,int> &db)
{
int cnt=qa.size();
for(int i=0;i<cnt;i++)
{
auto t=qa.front();qa.pop();
for(int len=1;len<=n;len++)//l~r 移动到k后面
for(int l=0;l+len-1<n;l++)
{
int r=l+len-1;
for(int k=r+1;k<n;k++)//r+1~k
{
string s=t.substr(0,l)+t.substr(r+1,k-r)+t.substr(l,len)+t.substr(k+1);
if(da.count(s)) continue;
if(db.count(s)) return da[t]+db[s]+1;
da[s]=da[t]+1;
qa.push(s);
}
}
}
cout<<qa.size()<<endl;
return -1;
}
*/
int extend(string q[],int &hh,int &tt,unordered_map<string,int> &da,unordered_map<string,int> &db)
{
int cnt=tt-hh+1;
for(int i=0;i<cnt;i++)
{
auto t=q[hh++];
for(int len=1;len<=n;len++)//l~r 移动到k后面
for(int l=0;l+len-1<n;l++)
{
int r=l+len-1;
for(int k=r+1;k<n;k++)//r+1~k
{
string s=t.substr(0,l)+t.substr(r+1,k-r)+t.substr(l,len)+t.substr(k+1);
if(da.count(s)) continue;
if(db.count(s)) return da[t]+db[s]+1;
da[s]=da[t]+1;
q[++tt]=s;
}
}
}
return -1;
}
int bfs(string &x,string y)
{
//模拟队列
string qa[N],qb[N];
int ta=-1,tb=-1,ha=0,hb=0;
unordered_map<string,int> da,db;
qa[++ta]=x,da[x]=0;
qb[++tb]=y,db[y]=0;
int t;
int cnt=2;
while(cnt--)
{
t=extend(qa,ha,ta,da,db);
if(t!=-1) return t;
t=extend(qb,hb,tb,db,da);
if(t!=-1) return t;
}
/*STL队列
queue<string> qa,qb;
unordered_map<string,int> da,db;
qa.push(x),da[x]=0;
qb.push(y),db[y]=0;
int t;
int cnt=2;
while(cnt--)
{
t=extend(qa,da,db);
if(t!=-1) return t;
t=extend(qb,db,da);
if(t!=-1) return t;
}
*/
return 11;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
string a,b;
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
a+=char(x+'0');
}
for(int i=0;i<n;i++) b+=char(i+'1');
if(a==b) printf("0\n");
else
{
int res=bfs(a,b);
if(res>=5) printf("5 or more\n");
else printf("%d\n",res);
}
}
return 0;
}
#include[HTML_REMOVED]
#include[HTML_REMOVED]
#include[HTML_REMOVED]
using namespace std;
const int N = 15, M = 3e5+ 10;
#define ull unsigned long long
int n;
char s[N], t[N], q1[M][N], q2[M][N], tmp[N];
unordered_map[HTML_REMOVED] vis;
ull f(char* s) {
ull res = 0;
for (int i = 0; i < n; i++)
res = res * 131 + s[i];
return res;
}
int bfs() {
for (int i = 0; i < n; i) t[i] = ‘A’ + i + 1;
vis.clear();
vis[f(s)] = 1;
if (vis[f(t)] == 1) return 0;
vis[f(t)] = 2;
int c1 = 0, c2 = 0, i = 0, j = 0, e1 = 0, e2 = 0;
memcpy(q1[0], s, sizeof s);
memcpy(q2[0], t, sizeof t);
for (int p = 1; p <= 2; p) {
for (; i <= e1; i) {
for (int l = 0; l < n; l)
for (int r = l; r < n; r)
for (int k = r + 1; k < n; k) {
memcpy(tmp, q1[i], sizeof tmp);
int x, y;
for (x = r + 1, y = l; x <= k; x, y) tmp[y] = q1[i][x];
for (x = l; x <= r; x, y) tmp[y] = q1[i][x];
auto& v = vis[f(tmp)];
if (!v) {
v = 1;
if (p == 1) memcpy(q1[c1], tmp, sizeof tmp);
}
else if (v == 2) return 2 * p - 1;
}
}
for (; j <= e2; j) {
for (int l = 0; l < n; l)
for (int r = l; r < n; r)
for (int k = r + 1; k < n; k) {
memcpy(tmp, q2[j], sizeof tmp);
int x, y;
for (x = r + 1, y = l; x <= k; x, y) tmp[y] = q2[j][x];
for (x = l; x <= r; x, y) tmp[y] = q2[j][x];
auto& v = vis[f(tmp)];
if (!v) {
v = 2;
if (p == 1) memcpy(q2[c2], tmp, sizeof tmp);
}
else if (v == 1) return 2 * p;
}
}
e1 = c1, e2 = c2;
}
}
int main() {
int T;
cin >> T;
while (T–) {
cin >> n;
int x;
for (int i = 0; i < n; i++) {
cin >> x;
s[i] = x + ‘A’;
}
int ans = bfs();
if (ans == -1) printf(“5 or more\n”);
else printf(“%d\n”, ans);
}
return 0;
}
这个算是纯双向bfs嘛 调了2天qwq 一开始用string没搞过去
加上启发式函数就行了, 双向搜时当实际距离加上预测距离>=5时, 当前状态就可以跳过
双向 bfs的问题不知道解决没有我也搞不定了
双向bfs太暴力了,没有任何剪枝,可以试试A*的算法。
嗯嗯,确实不过我记得y总视频提到了双向bfs?
为啥往外扩展的时候把队列中的所有元素都出队?
因为队列里的元素都是相同的操作数操作了一次or两次