読者です 読者をやめる 読者になる 読者になる

AOJ 2443

探索。答えはn-1以下であることとか、半分全列挙系を使えばいいとかを考えればいける。手元でテストするのが重過ぎる。

#include<stdio.h>
#include<algorithm>
using namespace std;
int b[10];
long long c[5][4200000];
long long d[5][4200000];
int C[5];
int D[5];
long long p10[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000LL};
int main(){
	int a;scanf("%d",&a);
	long long S=0;
	for(int i=0;i<a;i++){
		scanf("%d",b+i);
		b[i]--;
		S*=10;
		S+=b[i];
	}
	int ans=a-1;
	int start=123456789;
	for(int i=0;i<10-a;i++)start/=10;
	c[0][C[0]++]=start;
	d[0][D[0]++]=S;
	for(int i=0;i<4;i++){
	//	printf("%d %d\n",C[i],D[i]);
		for(int j=0;j<C[i];j++){
			for(int k=0;k<a;k++){
				for(int l=k+1;l<a;l++){
					long long TO=0;
					for(int m=0;m<a;m++){
						TO*=10;
						if(k<=m&&m<=l)TO+=c[i][j]%p10[a-k-l+m]/p10[a-k-l+m-1];
						else TO+=c[i][j]%p10[a-m]/p10[a-1-m];
					}
					c[i+1][C[i+1]++]=TO;
				}
			}
		}
		for(int j=0;j<D[i];j++){
			for(int k=0;k<a;k++){
				for(int l=k+1;l<a;l++){
					long long TO=0;
					for(int m=0;m<a;m++){
						TO*=10;
						if(k<=m&&m<=l)TO+=d[i][j]%p10[a-k-l+m]/p10[a-k-l+m-1];
						else TO+=d[i][j]%p10[a-m]/p10[a-1-m];
					}
					d[i+1][D[i+1]++]=TO;
				}
			}
		}
	}
	for(int i=0;i<5;i++){
		std::sort(d[i],d[i]+D[i]);
	}
	for(int i=0;i<a-1;i++){
		int n=i/2;
		bool ok=false;
		for(int j=0;j<C[n];j++)if(binary_search(d[i-n],d[i-n]+D[i-n],c[n][j]))ok=true;
		if(ok){
			printf("%d\n",i);
			return 0;
		}
	}
	printf("%d\n",ans);
}