好的满分方法:传送门
它讲的非常详细,仔细一看方法和我的差不多,不同点在于斜的两个标记和竖的标记它分别为这个开了三个数组,然后用来存这里是否已经被占领,然后递归完下一个再恢复,我本来也想这样的,但我只想到用一个二维数组的方法,这样是不可能回溯的,所以导致我最后一个数据超时而他没超时
通过这题的收获是,大的解决不了的时候化成小的,比如说我就应该再多建几个数组完成回溯的,可是我没有想到,很遗憾
自己的不ok87分方法:
ps.把没满分的方法放这是给自己以后看的,代码存博客园比存电脑硬盘好管理多了
思路:
第一次,可以选1,2,3,4,5,6
接下来,每一次选都不能处于前面子的攻击范围内,这个用sign标记,然后一直递归就好了
评析:
这个做法6~12都可以,但是当n=13时会超时,因为没有优化过,而且我没有想到怎么优化
然后中间除了个错误,以后都不写std::ios::sync_with_stdio(false)了,因为我根本只是照猫画虎,不懂这东西,很容易出错
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; int ans=0,n; int a[100],sign[100],t=0; int f(int new_i) { if(new_i==n+1) { if(t<3){ for(int i=1;i<=n;i++) { printf("%d ",a[i]); } printf(" "); } ans++; t++; return 0; } for(int i=1;i<=n;i++) { for(int j=1;j<=new_i-1&&new_i!=1;j++) { sign[a[j]]=1; int left=a[j]-(new_i-j); int right=a[j]+(new_i-j); if(left>=1) sign[left]=1; if(right<=n) sign[right]=1; } if(sign[i]!=1||new_i==1) { a[new_i]=i; memset(sign,0,sizeof(sign)); f(new_i+1); } memset(sign,0,sizeof(sign)); } return 0; } int main() { scanf("%d",&n); f(1); printf("%d",ans); }