不知道自己算不算想复杂了,我把方块图案抽象成一个称为myDraft的模型出来。第一步是将符号化的图案抽象成1和0构成的矩阵,当然这一步很容易想到,然后,在这个矩阵的基础上,将每一行和每一列看成是一系列的比特位,假设某一行是:@-@---,第一步就是将其转化成:10100,然后再将其转化成一个十进制数,即2^4+2^2=20,保存下这个值,所有的行和列都进行同样的处理,处理的结果就是myDraft了。
为什么要搞一个这样的myDraft出来呢?当然是为了拿一坨见鬼的翻转和比较的方便了。以两矩阵的比较为例,如果你每次都老老实实遍历两个矩阵的matrix[i][j]做对比,时间开销为O(n2)。进行翻转的话,需要对每个元素进行( i , j )à(n-1-j, i )的坐标转换,也是O(n2)是无法避免的。对时间效率的追求,有了myDraft。
不管你怎么旋转,都不会改变每一行/列中的1或是0——貌似是句废话,呵呵~同时更重要的是,旋转中行和列的转化是有规律的,在旋转中,只要利用这个规律相应改变蓝色部分,也就是存储在vector里面的值,就可以了。
旋转规律:
l 原Rowà新Column: vector中元素位置前后倒置,元素值进行myNegate()转换;
l 原Columnà新Row:vector中元素位置不变,元素值进行myNegate()转换。
myNegate是什么意思呢?我是受到了汇编语言里面的循环移位(ROR、ROL)的启发。举个例子来说,就是110变成011,说白了就是比特位的翻转。为什么要这么做,看看上面的图应该就知道了。
下面是整个程序的源代码。代码还可以优化,不过差不多是语言级的优化了吧。没细看了。总之这道题AC后觉得挺爽的,觉得自己的模型建立得比较好!建模能力确实很重要啊!
/*
ID: fairyroad
PROG: transform
LANG: C++
*/
#include<fstream>
#include<vector>
using namespace std;
ofstream fout ("transform.out");
ifstream fin ("transform.in");
/* The model of this program treats each row or column of the square pattern(myDraft) as a series of bits
for example,"@-@--" is valued as 10100, which equals to 2^4+2^2=20
The input: @-@ 101 101
--- --> 000 rotate90: 100
@@- 110 001
will be stored like this: (3, (5,0,6), (5,1,4) ), after rotation: (3, (5,4,1), (6,0,5) )
Through this model,the rotation and compare will be very easy.
*/
struct myDraft
{
vector<int> row, column; // Respectively records the summary of each row or column
int length;
myDraft(int n) : length(n), row(n,0), column(n,0) {}
myDraft(const myDraft& other) : length(other.length), row(other.row), column(other.column) {}
void getInput()
{
int times=length;
while (times)
{
int len=length, res=0, flag=0;
char ch;
while (len) {
fin>>ch;
flag= ch=='@'?1:0;
res=(res<<1)+flag;
column[length-len]= (column[length-len]<<1)+flag;
--len;
}
row[length-times]=res;
--times;
}
}
inline myDraft rotate90()
{
myDraft tmp(length);
//tmp.row=column;
for (int i=0; i<length; i++){
tmp.column[i]=row[length-i-1];
tmp.row[i]= myNegate(column[i]);
}
return tmp;
}
myDraft rotate180() { return rotate90().rotate90(); }
myDraft rotate270() { return rotate180().rotate90(); }
inline myDraft flip()
{
myDraft tmp(*this);
int guard=length>>1;
int times=1, header=0, tail=length-1;
//vector<int>::iterator header=tmp.column.begin(), tail= --tmp.column.end();
while (times<=guard)
{
int temp=tmp.column[header];
tmp.column[header]=tmp.column[tail];
tmp.column[tail]=temp;
tmp.row[header]=myNegate(tmp.row[header]);
tmp.row[tail]=myNegate(tmp.row[tail]);
++header; --tail; ++times;
}
if (header==tail) tmp.row[tail]=myNegate(tmp.row[tail]);
return tmp;
}
inline bool operator==(const myDraft& other) { return row==other.row && column==other.column; }
private:
inline int myNegate(int candicate) // if the candicate is 4(100), then change it into 001
{
int count=length, res=0;
while(count){
int lowbit=1; lowbit&=candicate;
res=(res<<1)+lowbit;
candicate>>=1;
--count;
}
return res;
}
};
int measure( myDraft& src, myDraft& dest)
{
if (src.rotate90()==dest) return 1;
else if (src.rotate180()==dest) return 2;
else if (src.rotate270()==dest) return 3;
return 0;
}
int main()
{
int n;
fin>>n;
myDraft src(n), dest(n);
src.getInput();
dest.getInput();
int res=measure(src, dest);
if(res) {fout<<res<<endl; return 0;}
else{
myDraft tmp=src.flip();
if(tmp==dest) { fout<<4<<endl; return 0; }
else if(measure(tmp, dest)) { fout<<5<<endl; return 0; }
}
if (src==dest) { fout<<6<<endl; return 0; }
fout<<7<<endl;
return 0;
}