最少交换次数
bfs,折半搜索,因为直接搜大概有(12)^13?因为每个状态都会扩展出m种状态大概是(12)^13,然而可以折半搜索,只搜一半,状态数变成(12)^7可以接受,但是事实上极限数据要跑很长很长时间,据说正解是启发式搜索?没学过
#include<iostream> #include<map> #include<set> #include<queue> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; string S,tar; map<string, int> mp; map<string, int> mp1; queue<string>q; queue<string>temp; int n,m,p; int a[30],b[30]; ll Hash(string s) { ll ret=0; for(int i=1;i<=n;i++) {ret*=171;ret+=a[i];} return ret; } bool bfs() { q.push(S); mp[S]=0; while(!q.empty()) { string s = q.front(); int step = mp[s]; q.pop(); for(int i=1;i<=m;i++) { swap(s[a[i]],s[b[i]]); if(!mp.count(s)) { if(s==tar) {printf("%d\n",step+1);return false;} temp.push(s);mp[s] = step + 1; } swap(s[a[i]],s[b[i]]); } } return true; } void bfs1() { q.push(tar); mp1[tar] = 0; while(!q.empty()) { string s=q.front();q.pop();int step=mp1[s]; for(int i=1;i<=m;i++) { swap(s[a[i]],s[b[i]]); if(mp.count(s)) { printf("%d\n",mp[s]+step+1); return; } if(!mp1.count(s)) { q.push(s); mp1[s]=step+1; } swap(s[a[i]],s[b[i]]); } } } int main() { cin>>n>>m; for(int i=1;i<=n;i++) { cin>>p; S+=(char)(p+'a'); tar+=(char)(i+'a'); } // cout<<S<<'\n'<<tar<<'\n'; for(int i=1;i<=m;i++) cin>>a[i]>>b[i],a[i]--,b[i]--; if(S==tar) {printf("0\n");return 0;} if(bfs()) bfs1(); return 0; }