Uva 10237 - Bishops 回溯+打表 0msAC

这题肝了一个晚上,明明是回溯专题,类型也是回溯,最后回溯解法写出来了,也尽力优化了,一直TLE,最后题解是DP,好气啊!DP解法我在想想。

LL cnt=0;
int n,k;
int flag_45[20],flag_135[20];
void solve(int prev_s,int remain,int n){
    if(remain==0){
        cnt++;
        return ;
    }      
	for(int s=prev_s+1;s<=2*n-1-remain;s++){
		for(int i=0;i<n;i++){
			int j=s-i;
			if(j>=0&&j<n&&!flag_45[i+j]&&!flag_135[n-1+j-i]){
				flag_45[i+j]=flag_135[n-1+j-i]=1; 
				solve(s,remain-1,n);
				flag_45[i+j]=flag_135[n-1+j-i]=0;
			}
		}
	}   
}
int main()
{  
   while(scanf("%d%d",&n,&k),n+k){
   	cnt=0;
	FILL(flag_45,0);
	FILL(flag_135,0);
	solve(-1,k,n);
	printf("%lld\n",cnt);
   }
   return 0;	
}

一个小时后,跑步时,想到 打表 打表 打表 我太聪明了,查询的总数很少,直接交超时,但本机跑出所有答案也不过10s,下面是打表结果:

1,1,
1,4,4,0,0,
1,9,26,26,8,0,0,0,0,0,
1,16,92,232,260,112,16,0,0,0,0,0,0,0,0,0,0,
1,25,240,1124,2728,3368,1960,440,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,36,520,3896,16428,39680,53744,38368,12944,1600,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,49,994,10894,70792,282248,692320,1022320,867328,389312,81184,5792,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,64,1736,26192,242856,1444928,5599888,14082528,22522960,22057472,12448832,3672448,489536,20224,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,

直接开数组存好,O(1)输出就完事了,可见回溯解法弄出来了,超时也莫慌,一般数据量小的时候,在本机离线跑一遍,把结果存好输出,这真的是一个好方法,此时我想说,暴力算个啥,打表出奇迹,真开心。
下面是混合AC代码:

LL cnt=0;
int n,k;
int flag_45[20],flag_135[20];
//回溯法 
void solve(int prev_s,int remain,int n){
    if(remain==0){
        cnt++;
        return ;
    }      
	for(int s=prev_s+1;s<=2*n-1-remain;s++){
		for(int i=0;i<n;i++){
			int j=s-i;
			if(j>=0&&j<n&&!flag_45[i+j]&&!flag_135[n-1+j-i]){
				flag_45[i+j]=flag_135[n-1+j-i]=1; 
				solve(s,remain-1,n);
				flag_45[i+j]=flag_135[n-1+j-i]=0;
			}
		}
	}   
}
//12.33s打表结果
int ans[9][65]=
{
{},
{1,1},
{1,4,4,0},
{1,9,26,26,8,0},
{1,16,92,232,260,112,16,0},
{1,25,240,1124,2728,3368,1960,440,32,0},
{1,36,520,3896,16428,39680,53744,38368,12944,1600,64,0},
{1,49,994,10894,70792,282248,692320,1022320,867328,389312,81184,5792,128,0,},
{1,64,1736,26192,242856,1444928,5599888,14082528,22522960,22057472,12448832,3672448,489536,20224,256,0}
};
int main()
{  
   while(scanf("%d%d",&n,&k),n+k){
//   回溯解法 TLE 当输入8 11、12 等样例时 需要1~2秒时间计算,不过打表时就算它跑个10分钟能出结果这样能A题 打表出奇迹 
//   cnt=0;
//	FILL(flag_45,0);
//	FILL(flag_135,0);
//	solve(-1,k,n);
//	printf("%lld\n",cnt);
    //想一想此时的酸爽
	printf("%d\n",ans[n][k]); 
    }
//打表 
//   for(int n=1;n<=8;n++){
//   	for(int k=0;k<=n*n;k++){
//   		    cnt=0;
//   			solve(-1,k,n);
//	        printf("%lld,",cnt);
//	   }
//	   printf("\n");
//   } 
   return 0;	
}

猜你喜欢

转载自blog.csdn.net/Csdn_jey/article/details/90416198