九野的博客,转载请注明出处:http://blog.csdn.net/acmmmm/article/details/11391275
题意:该矩阵中,可以顺时针或逆时针旋转每一圈,问旋转至少几次可以使主对角线和副对角线和最大
下面代码先计算每一圈的和最大,最后加上中间的点
题目保证矩阵边长为奇数
做起来有点繁琐,下面k表示第k圈,最中间是第0圈,只要for那一圈的第一排数字即可。
#include <iostream> #include <string> #include <cstring> #include <algorithm> #include <cstdio> #include <cctype> #include <queue> #include <stdlib.h> #include <cstdlib> #include <set> #include <math.h> #include <vector> #define inf 107374182 #define N 105 #define im -1000000 #define ll int using namespace std; inline ll Max(ll a,ll b){return a>b?a:b;} inline ll Min(ll a,ll b){return a<b?a:b;} int map[N][N],n; int sum(int k,int h,int l){ k=(n/2)+1-k; return map[k+h][k+l]; } int sum1(int k,int h,int l){ int len=k*2; k=(n/2)+1-k; int x=h,y=l; if(x>len){y+=(x-len);x=len;} if(x<0){y-=0-x;x=0;} if(y>len){x+=(y-len);y=len;} if(y<0){x-=0-y;y=0;} return map[k+x][k+y]; } int GO(int x,int y,int k){ if(x==0)return Min(y,k-y); return Min(x,k-x); } int abs(int k,int i){ if(i>k)return i-2*(i-k); return i+2*(k-i); } int main(){ ll i,j,k,go; while(scanf("%d",&n),n) { for(i=1;i<=n;i++) for(j=1;j<=n;j++) scanf("%d",&map[i][j]); int step=0,ans=0; int zhongdian=(n/2)+1; for(k=1;k<=(n>>1);k++) { int len=k*2,maxx=-1,temp; go=10000; for(i=0;i<k*2+1;i++) { temp=sum(k,0,i)+sum(k,len,abs(k,i)); temp+= sum1(k,0,i+len)+sum1(k,len,abs(k,i)-len); if(temp>maxx) { maxx=temp; go=GO(0,i,len); } else if(temp==maxx) if(go>GO(0,i,len)) go=GO(0,i,len); } step+=go; ans+=maxx; } printf("%d %d\n",ans+map[zhongdian][zhongdian],step); } return 0; } /* 5 9 3 2 5 9 7 4 7 5 4 6 9 3 9 3 5 2 8 7 2 9 9 4 1 9 */