Description
战神阿瑞斯听说2008年在中华大地上,将举行一届规模盛大的奥林匹克运动会,心中顿觉异常兴奋,他想让天马在广阔的天空上,举行一场精彩的天马队列变换表演。首先,战神安排n头高度不同的天马,排成一列。然后重复下面的变换:让中间的天马出列,然后该匹天马可以排在对首,也可以排在队尾,这样称为一次变换,直到出现这一列天马按从低到高的顺序排列为止。那么从初始状态到目标状态最少需要多少次变换呢?你能给战神阿瑞斯参谋参谋吗?
Input
输入文件horse.in中有两行,第一行只有一个整数n,表示天马数。
第二行有n个正整数,分别表示n匹天马的高度,每两个数字中间用一个空格分隔。
Output
输出文件horse.out只有一行,该行只有一个正整数,表示从初始状态到目标状态最少需要的变换次数。如果无论如何变换都不能得到从低到高的排列,则输出已行“No Answer”(不包括引号)。
Sample Input
3
179 173 175
Sample Output
2
Data Constraint
Hint
【数据限制】
100%的数据:n只取3、5、7、9四个数字中的一个,且天马的高度为160-190之间的整数。
Solution
对于n=3,发现答案实际上等于逆序对数。
对于n=5or7,可以双向bfs,用标记记录状态。
对于n=9,则用哈希数组(玄学)记录。
注意双向bfs的时候要取两个队列中头指针步数较小的进行扩展,否则答案会错。
Code1(70pts)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define I int
#define F(i,a,b) for(I i=a;i<=b;i++)
#define Fd(i,a,b) for(I i=a;i>=b;i--)
#define N 15
using namespace std;
I n,m,x,y,a1,a2,a3,ans=-1,a[N],cnt,p[10][2],l,r,ll,rr,S,T,f[3200000],g[3200000],b[3200000],bz[3200000];
struct node{I v,id;}s[N];
I cmp(node x,node y){return x.v<y.v;}
I main(){
freopen("page.in","r",stdin);
freopen("page.out","w",stdout);
scanf("%d",&n);
F(i,1,n) scanf("%d",&a[i]);
if(n==3) printf("%d\n",(a[1]>a[2])+(a[1]>a[3])+(a[2]>a[3]));
else if(n==5||n==7){
p[1][0]=p[1][1]=1;
F(i,2,8){p[i][0]=p[i-1][0]*6,p[i][1]=p[i-1][1]*8;}
F(i,1,n) s[i]=node{a[i],i};
sort(s+1,s+1+n,cmp);
F(i,1,n) a[s[i].id]=i;
S=T=0;
F(i,1,n){
S+=a[i]*p[i][n/7];
T+=i*p[i][n/7];
}
memset(b,255,sizeof b);
memset(bz,255,sizeof bz);
l=r=ll=rr=0;
b[f[++r]=S]=bz[g[++rr]=T]=0;
while(l<r||ll<rr){
if(l<r){
x=f[++l];
if(bz[x]>=0){ans=bz[x]+b[x];break;}
a1=x%p[n/2+1][n/7],a2=(x%p[n/2+2][n/7])/p[n/2+1][n/7],a3=x/p[n/2+2][n/7];
y=a1+a3*p[n/2+1][n/7]+a2*p[n][n/7];
if(bz[y]>=0){ans=bz[y]+b[x]+1;break;}
if(b[y]<0) b[f[++r]=y]=b[x]+1;
y=a2+a1*p[2][n/7]+a3*p[n/2+2][n/7];
if(bz[y]>=0){ans=bz[y]+b[x]+1;break;}
if(b[y]<0) b[f[++r]=y]=b[x]+1;
}
if(ll<rr){
x=g[++ll];
if(b[x]>=0){ans=b[x]+bz[x];break;}
a1=x%p[2][n/7],a2=(x%p[n/2+2][n/7])/p[2][n/7],a3=x/p[n/2+2][n/7];
y=a2+a1*p[n/2+1][n/7]+a3*p[n/2+2][n/7];
if(b[y]>=0){ans=b[y]+bz[x]+1;break;}
if(bz[y]<0) bz[g[++rr]=y]=bz[x]+1;
a1=x%p[n/2+1][n/7],a2=(x%p[n][n/7])/p[n/2+1][n/7],a3=x/p[n][n/7];
y=a1+a3*p[n/2+1][n/7]+a2*p[n/2+2][n/7];
if(b[y]>=0){ans=b[y]+bz[x]+1;break;}
if(bz[y]<0) bz[g[++rr]=y]=bz[x]+1;
}
}
if(ans==-1) printf("No Answer\n");
else printf("%d\n",ans);
}
else{
}
return 0;
}
Code2(100pts)
对于不同的质数答案可能会不一样,母鸡......
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define I int
#define F(i,a,b) for(I i=a;i<=b;i++)
#define Fd(i,a,b) for(I i=a;i>=b;i--)
#define N 15
#define M 372871
#define MM 372871
using namespace std;
I n,m,x,y,k,now,a1,a2,a3,ans=-1,a[N],p[13],l,r,ll,rr,S,T,f[1000000],g[1000000],s[372881],t[372881],b[372881],bz[372881];
struct node{I v,id;}o[N];
I cmp(node x,node y){return x.v<y.v;}
I pd(I x){
F(j,2,x-1) if(x%j==0) return 0;
return 1;
}
I h(I x){
k=x%M;
while(b[k]&&b[k]!=x) if(++k==M) k=0;
return k;
}
I ha(I x){
k=x%MM;
while(bz[k]&&bz[k]!=x) if(++k==MM) k=0;
return k;
}
void ins(I type){
if(type==1){
m=ha(y);
if(bz[m]==y) ans=t[m]+s[now]+1;
m=h(y);
if(!b[m]){f[++r]=y,s[m]=s[now]+1;}
}
else{
m=h(y);
if(b[m]==y) ans=s[m]+t[now]+1;
m=ha(y);
if(!bz[m]){g[++rr]=y,t[m]=t[now]+1;}
}
}
I main(){
freopen("page.in","r",stdin);
freopen("page.out","w",stdout);
/*F(i,502780,502880) if(pd(i)){
printf("%d\n",i);
}*/
scanf("%d",&n);
F(i,1,n) scanf("%d",&a[i]);
if(n==3) printf("%d\n",(a[1]>a[2])+(a[1]>a[3])+(a[2]>a[3]));
else{
p[1]=p[1]=1;
F(i,2,11) p[i]=p[i-1]*10;
F(i,1,n) o[i]=node{a[i],i};
sort(o+1,o+1+n,cmp);
F(i,1,n) a[o[i].id]=i;
S=T=0;
F(i,1,n){
S+=a[i]*p[i];
T+=i*p[i];
}
l=r=ll=rr=0;
m=h(f[++r]=S);b[m]=S;
m=ha(g[++rr]=T);bz[m]=T;
while(l<r||ll<rr){
if(l<r&&s[h(f[l+1])]<=t[ha(g[ll+1])]){
x=f[++l],now=h(x);
// m=ha(x);
// if(bz[m]==x){ans=t[m]+s[now];break;}
a1=x%p[n/2+1],a2=(x%p[n/2+2])/p[n/2+1],a3=x/p[n/2+2];
y=a1+a3*p[n/2+1]+a2*p[n];
ins(1);
if(ans>=0) break;
y=a2+a1*p[2]+a3*p[n/2+2];
ins(1);
if(ans>=0) break;
}
if(ll<rr&&s[h(f[l+1])]>=t[ha(g[ll+1])]){
x=g[++ll],now=ha(x);
// m=h(x);
// if(b[m]==x){ans=s[m]+t[now];break;}
a1=x%p[2],a2=(x%p[n/2+2])/p[2],a3=x/p[n/2+2];
y=a2+a1*p[n/2+1]+a3*p[n/2+2];
ins(0);
if(ans>=0) break;
a1=x%p[n/2+1],a2=(x%p[n])/p[n/2+1],a3=x/p[n];
y=a1+a3*p[n/2+1]+a2*p[n/2+2];
ins(0);
if(ans>=0) break;
}
}
if(ans>=0&&ans<=30) printf("%d\n",ans);else printf("No Answer\n");
}
return 0;
}