数学建模那确实是很重要滴呀!USACO Solution Code(4):Transformations

不知道自己算不算想复杂了,我把方块图案抽象成一个称为myDraft的模型出来。第一步是将符号化的图案抽象成10构成的矩阵,当然这一步很容易想到,然后,在这个矩阵的基础上,将每一行和每一列看成是一系列的比特位,假设某一行是@-@---,第一步就是将其转化成: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àRowvector中元素位置不变,元素值进行myNegate()转换。

myNegate是什么意思呢?我是受到了汇编语言里面的循环移位(RORROL)的启发。举个例子来说,就是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;

}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值