洛谷 2239 螺旋矩阵
翻了翻题解,发现我的这个方法好像并没有被写过,也许是这个方法太菜了,但是还是可以AC的。
首先呢:1 ≤ n ≤ 30,000.....暴力就别想了,最多50分
于是就开始在暴力的基础上找方法,无意发现,如果我们开始先将矩阵一层一层的剥开,直到目标位置在新矩阵的最外层是停止。此时最坏情况,目标点在30000X30000矩阵的的(2,1)位置(如果搜索方向不同可能会不一样,但结论相同),我们也只需循环填120000-4个数就可以找到答案。
重要的是“剥开”矩阵的过程,先贴代码:
int c=min(min(x-1,n-x),min(y-1,n-y));//确定要剥开的层数 while(c--) { ans+=n*n-(n-2)*(n-2); //记录剥掉的数字总数 n-=2; //原矩阵边长减2 --x;--y; //目标位置也随之变化 }
另外我们也不必真正的将数字填上,用tot记录好填到哪个数了,到时候输出tot与前面算出ans的和即可。
而且由于我们已经保证目标点在新矩阵的最外层,所以不避开任何数组进行记录,填数时撞到边界就转向。
AC代码:
#include<bits/stdc++.h> using namespace std; int n,x,y,tot=1,i=1,j=0; long long ans=0; bool pd(int xx,int yy) { if(xx==x&&yy==y) { cout<<tot+ans-1; return 1; } return 0; } int main() { scanf("%d%d%d",&n,&x,&y); int c=min(min(x-1,n-x),min(y-1,n-y));//确定要剥开的层数 while(c--) { ans+=n*n-(n-2)*(n-2); //记录剥掉的数字总数 n-=2; //原矩阵边长减2 --x;--y; //目标位置也随之变化 } while(tot<=n*n) { while(j+1<=n) {++j;++tot;if(pd(i,j)) return 0;} while(i+1<=n) {++i;++tot;if(pd(i,j)) return 0;} while(j-1>=1) {--j;++tot;if(pd(i,j)) return 0;} while(i-1>=1) {--i;++tot;if(pd(i,j)) return 0;} } }