将所有的康托展开扫一遍,然后逆康托展开,以此求转移权值
然后建图,只需要建一次图,因为状态转移是固定的
然后每一次询问跑一次最短路就行
(有一部分人用的是BFS+hash,
(有一部分人用的是A*
一开始上面两种思路觉得都会TLE,但是最后大家都没有...感谢大A熊的代码
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <ctime>
#define maxn 500005
#define inf 10000000
using namespace std;
int fac[12] = {1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800};
int b[12] = {0,1,2,3,4,5,6,7,8,9,10,11};
int Hash(int s[],int fac[],int len)
{
int ktzk = 0;
for(int i = 0;i < len;i++)
{
int cnt = 0;
for(int j=i+1;j<len;j++)
if(s[j]<s[i]) cnt++;
ktzk+=fac[len - 1 - i]*cnt;
}
return ktzk;
}
void get_ans(int result[],int b[],int fac[],int len,int n)
{
for(int i=0;i<12;i++) b[i] = i;
for(int j=0;j<len;j++)
{
int temp = n/fac[len - 1 - j];
result[j] = b[temp];
for(int i=temp;i<len-1;i++)
b[i] = b[i+1];
n -= temp*fac[len - 1 - j];
}
}
int head[maxn],next[4*maxn],node[4*maxn],val[4*maxn];
int ch,cv,start,target,Index;
int T[9];
int MaxIndex;
void Init()
{
memset(head,0,sizeof(head));
memset(next,0,sizeof(next));
Index = 0;
}
void Addedge(int from,int to,int v)
{
Index++;
next[Index] = head[from];
node[Index] = to;
val[Index] = v;
head[from] = Index;
}
struct HeapNode
{
int d,u;
bool operator <(const HeapNode & rhs) const
{
return d > rhs.d;
}
};
bool vis[maxn];
int d[maxn];
int Dij(int s,int t)
{
priority_queue<HeapNode> Q;
for(int i=0;i<=MaxIndex;i++) d[i] = inf;
d[s] = 0;
memset(vis,false,sizeof(vis));
Q.push((HeapNode){0,s});
while(!Q.empty())
{
HeapNode x = Q.top();Q.pop();
int u = x.u;
if(u == t) return d[u];
if(vis[u]) continue;
vis[u] = true;
for(int p = head[u];p;p=next[p])
{
if(d[ node[p] ]>d[u]+(val[p]==0?ch:cv))
{
d[node[p]] = d[u] + (val[p]==0?ch:cv);
Q.push((HeapNode){d[node[p]],node[p]});
}
}
}
}
int main()
{
int MaxT[9] = {8,7,6,5,4,3,2,1,0};
MaxIndex = Hash(MaxT,fac,9);
Init();
for(int i=0;i<=MaxIndex;i++)
{
int T1[12],T2[12];
get_ans(T1,b,fac,9,i);
int pos,to;
for(int j=0;j<9;j++) if(T1[j] == 0) pos = j;
//Sleep(500);
for(int j=0;j<9;j++) T2[j] = T1[j];
swap(T2[pos],T2[(pos+1)%9]);
to = Hash(T2,fac,9);
Addedge(i,to,0);
//cout<<i<<' '<<to<<' '<<ch<<endl;
for(int j=0;j<9;j++) T2[j] = T1[j];
swap(T2[pos],T2[(pos+8)%9]);
to = Hash(T2,fac,9);
Addedge(i,to,0);
//cout<<i<<' '<<to<<' '<<ch<<endl;
for(int j=0;j<9;j++) T2[j] = T1[j];
swap(T2[pos],T2[(pos+3)%9]);
to = Hash(T2,fac,9);
Addedge(i,to,1);
//cout<<i<<' '<<to<<' '<<ch<<endl;
for(int j=0;j<9;j++) T2[j] = T1[j];
swap(T2[pos],T2[(pos+6)%9]);
to = Hash(T2,fac,9);
Addedge(i,to,1);
//cout<<i<<' '<<to<<' '<<ch<<endl;
}
while(1)
{
scanf("%d%d",&ch,&cv);
if(ch == 0 && cv == 0) break;
for(int i=0;i<9;i++) scanf("%d",&T[i]);
start = Hash(T,fac,9);
for(int i=0;i<9;i++) scanf("%d",&T[i]);
target = Hash(T,fac,9);
//cout<<start<<' '<<target<<endl;
cout<<Dij(start,target)<<endl;
}
return 0;
}