分析
這是我第一次在ACM的題目中用OO的思想寫的程式,看到標程,竟不謀而合,結構是類似的。對正方形這個類分析,將會使問題變得簡單,我覺得OO的分析和設計挺關鍵的,其實我一開始也沒設計好,原先準備把7個bool函數當成類的成員方法,其實這個設計是不好的,有點過了。其實應該是把旋轉90度和軸對稱這兩個方法作為類的成員方法,這樣main中調用就方便自如了。
最後,我覺得搞ACM,不僅是把題目A掉,同時也應注意程式的結構設計,因為”程式是給人看的“。
2013/3/31
關於順時針旋轉90度,怎麼由原來的座標得到轉換後的座標,可以用電腦映像學裡二維變換的知識,將連續推廣到離散的,如所示。
為了與二維數組對應,我將座標系順時針旋轉了90度,這樣就與二維數組的下標情況對應了,假設n為4。
關於變換矩陣,先把參考點移到原點,再順時針旋轉90度,最後移回原來參考點。複合變換矩陣:
MATLAB程式如下:
clc;clear all;syms x y n;P = [x y 1];xF = (n - 1) / 2.0; % center = (xF yF)yF = xF;% theta = -pi / 2.0;Tt1 = [ 1 0 0; 0 1 0; -xF -yF 1 ];% 精度有損失% Tr = [% cos(theta) sin(theta) 0;% -sin(theta) cos(theta) 0;% 0 0 1% ];Tr = [ 0 -1 0; 1 0 0; 0 0 1 ];Tt2 = [ 1 0 0; 0 1 0; xF yF 1 ];Pt = P * Tt1 * Tr * Tt2;display(P);display(Pt);
變換結果
P = [ x, y, 1] Pt = [ y, n - x - 1, 1]
來源程式
// #define ONLINE_JUDGE#define MY_DEBUG#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <vector>#include <string>#include <algorithm>#include <cstdio>#include <cassert>using namespace std;class Square {private:typedef vector<char> vChar;typedef vector<vChar> vvChar;vvChar data;unsigned n;public:// 用邊長來構造Square (unsigned _n) : n(_n) {}Square rotateClockwise90() {Square tmp(n);for (unsigned int i = 0; i < tmp.n; ++i) {Square::vChar vcTmp;for (unsigned int j = 0; j < tmp.n; ++j){vcTmp.push_back(this->data[n - 1 - j][i]);}tmp.data.push_back(vcTmp);}return tmp;}Square rotateClockwise180() {return this->rotateClockwise90().rotateClockwise90();}Square rotateClockwise270() {return this->rotateClockwise180().rotateClockwise90();}Square reflecteHorizontal() {Square tmp(n);for (unsigned int i = 0; i < tmp.n; ++i) {Square::vChar vcTmp;for (unsigned int j = 0; j < tmp.n; ++j){vcTmp.push_back(this->data[i][n - j - 1]);}tmp.data.push_back(vcTmp);}return tmp;}bool operator==(const Square &other) const {if (this->n != other.n) {return false;}for (unsigned i = 0; i < n; ++i) {for (unsigned j = 0; j < n; ++j) {if (this->data[i][j] != other.data[i][j]) {return false;}}}return true;}friend istream & operator>>(istream& is, Square &s) {for (unsigned int i = 0; i < s.n; ++i) {Square::vChar vcTmp;for (unsigned int j = 0; j < s.n; ++j){char cTmp;cin >> cTmp;vcTmp.push_back(cTmp);}s.data.push_back(vcTmp);}return is;}friend ostream & operator<<(ostream& os, const Square &s) {for (unsigned int i = 0; i < s.n; ++i) {if (i >= 1) {cout << endl;}for (unsigned int j = 0; j < s.n; ++j){if (j >= 1) {cout << " ";}cout << s.data[i][j];}}return os;}};int main(){#ifndef ONLINE_JUDGEfreopen("transform.in", "r", stdin);freopen("transform.out", "w", stdout);#endifunsigned sideLen;cin >> sideLen;Square sa(sideLen);Square sb(sideLen);cin >> sa >> sb;#ifndef MY_DEBUGcout << "sa=\n" << sa << "\n" << endl;cout << "sb=\n" << sb << "\n" << endl;assert(sa.rotateClockwise270() == sa.rotateClockwise90().rotateClockwise90().rotateClockwise90());#endifif (sa.rotateClockwise90() == sb) {cout << "1" << endl;return 0;}if (sa.rotateClockwise180() == sb) {cout << "2" << endl;return 0;}if (sa.rotateClockwise270() == sb) {cout << "3" << endl;return 0;}if (sa.reflecteHorizontal() == sb) {cout << "4" << endl;return 0;}Square saRe(sa.reflecteHorizontal());if (saRe.rotateClockwise90() == sb|| saRe.rotateClockwise180() == sb|| saRe.rotateClockwise270() == sb) {cout << "5" << endl;return 0;}if (sa == sb) {cout << "6" << endl;return 0;}cout << "7" << endl;return 0;}
附:
標程註:它的旋轉函數中座標變換錯了。
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#define MAXN 10typedef struct Board Board;struct Board { int n; char b[MAXN][MAXN];};/* rotate 90 degree clockwise: [r, c] -> [c, n+1 - r] */Boardrotate(Board b){ Board nb; int r, c; nb = b; for(r=0; r<b.n; r++) for(c=0; c<b.n; c++) nb.b[c][b.n+1 - r] = b.b[r][c]; return nb;}/* reflect board horizontally: [r, c] -> [r, n-1 -c] */Boardreflect(Board b){ Board nb; int r, c; nb = b; for(r=0; r<b.n; r++) for(c=0; c<b.n; c++) nb.b[r][b.n-1 - c] = b.b[r][c]; return nb;}/* return non-zero if and only if boards are equal */inteqboard(Board b, Board bb){ int r, c; if(b.n != bb.n) return 0; for(r=0; r<b.n; r++) for(c=0; c<b.n; c++) if(b.b[r][c] != bb.b[r][c]) return 0; return 1;}Boardrdboard(FILE *fin, int n){ Board b; int r, c; b.n = n; for(r=0; r<n; r++) { for(c=0; c<n; c++) b.b[r][c] = getc(fin); assert(getc(fin) == '\n'); } return b;}voidmain(void){ FILE *fin, *fout; Board b, nb; int n, change; fin = fopen("transform.in", "r"); fout = fopen("transform.out", "w"); assert(fin != NULL && fout != NULL); fscanf(fin, "%d\n", &n); b = rdboard(fin, n); nb = rdboard(fin, n); if(eqboard(nb, rotate(b))) change = 1; else if(eqboard(nb, rotate(rotate(b)))) change = 2; else if(eqboard(nb, rotate(rotate(rotate(b))))) change = 3; else if(eqboard(nb, reflect(b))) change = 4; else if(eqboard(nb, rotate(reflect(b))) || eqboard(nb, rotate(rotate(reflect(b)))) || eqboard(nb, rotate(rotate(rotate(reflect(b)))))) change = 5; else if(eqboard(nb, b)) change = 6; else change = 7; fprintf(fout, "%d\n", change); exit(0);}
題目
Transformations
A square pattern of size N x N (1 <= N <= 10) black and white square tiles is transformed into another square pattern. Write a program that will recognize the minimum transformation that has been applied to the
original pattern given the following list of possible transformations:
- #1: 90 Degree Rotation: The pattern was rotated clockwise 90 degrees.
- #2: 180 Degree Rotation: The pattern was rotated clockwise 180 degrees.
- #3: 270 Degree Rotation: The pattern was rotated clockwise 270 degrees.
- #4: Reflection: The pattern was reflected horizontally (turned into a mirror image of itself by reflecting around a vertical line in the middle of the image).
- #5: Combination: The pattern was reflected horizontally and then subjected to one of the rotations (#1-#3).
- #6: No Change: The original pattern was not changed.
- #7: Invalid Transformation: The new pattern was not obtained by any of the above methods.
In the case that more than one transform could have been used, choose the one with the minimum number above.
PROGRAM NAME: transformINPUT FORMAT
| Line 1: |
A single integer, N |
| Line 2..N+1: |
N lines of N characters (each either `@' or `-'); this is the square before transformation |
| Line N+2..2*N+1: |
N lines of N characters (each either `@' or `-'); this is the square after transformation |
SAMPLE INPUT (file transform.in)
3@-@---@@-@-@@----@
OUTPUT FORMAT
A single line containing the the number from 1 through 7 (described above) that categorizes the transformation required to change from the `before' representation to the `after' representation.
SAMPLE OUTPUT (file transform.out)
1