很赞的一个模拟题目!
我能写出来说明我结构十分清晰!!
http://acm.timus.ru/problem.aspx?space=154&num=10
给 9 个 4 * 4 的数字矩阵。要求拼接成 10 * 10 的矩阵。保证有解。要求输出一组。
肯定是一个暴力题目,关键就是暴力的姿势问题。
一共有 9! 种排列方式,每个数字阵可以转 4次,那么 9! * 4^9 * check 肯定超时。
回忆起某个题目,按照序号排列最终矩阵——
0 1 2 3 4 5 6 7 8
接下来还剩下 9 - 4 = 5 个矩阵,5 * 4 = 20 种图形。
想起来一个以前做过的类似的题目,优化的方法是——记录0 2 4 6 8 这 4 个图形能被几个不同的数字矩阵填充,然后每次拿掉“剩余方案数”最小的。这样保证一定有解
比如{1 , 2}{1}{2 , 3}那么就先拿掉 1,{2 }{2 ,3}再拿掉 2最后拿掉3.
首先有个 Mat 的struct 分别是读入、输出、旋转、判断接壤。
#define 用的很好,减少了代码量
#include <functional> #include <algorithm> #include <iostream> #include <fstream> #include <sstream> #include <iomanip> #include <numeric> #include <cstring> #include <cassert> #include <cstdio> #include <string> #include <vector> #include <bitset> #include <queue> #include <stack> #include <cmath> #include <ctime> #include <list> #include <set> #include <map> using namespace std; #define DO(n) for ( int ____n ## __line__ = n; ____n ## __line__ -- ; ) #define ALL(A) A.begin(), A.end() #define BSC(A, x) (lower_bound(ALL(A), x) - A.begin()) #define CTN(T, x) (T.find(x) != T.end()) #define SZ(A) int(A.size()) #define PB push_back #define MP(A, B) make_pair(A, B) #define fi first #define se second typedef long long LL; typedef vector<int> VI; typedef map<int, int> MII; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template<class T> inline void RST(T &A){memset(A, 0, sizeof(A));} template<class T> inline void FLC(T &A, int x){memset(A, x, sizeof(A));} template<class T> inline void CLR(T &A){A.clear();} //} /** Constant List .. **/ //{ const int dx4[] = {-1, 0, 1, 0}; const int dy4[] = {0, 1, 0, -1}; const int dx8[] = {-1, 0, 1, 0 , -1 , -1 , 1 , 1}; const int dy8[] = {0, 1, 0, -1 , -1 , 1 , -1 , 1}; const int dxhorse[] = {-2 , -2 , -1 , -1 , 1 , 1 , 2 , 2}; const int dyhorse[] = {1 , -1 , 2 , -2 , 2 ,-2 , 1 ,-1}; const int MOD = 1000000007; //int MOD = 99990001; const int INF = 0x3f3f3f3f; const LL INFF = 1LL << 60; const double EPS = 1e-9; const double OO = 1e15; const double PI = acos(-1.0); //M_PI; //} template<class T> inline void checkMin(T &a,const T b){if (b<a) a=b;} template<class T> inline void checkMax(T &a,const T b){if (a<b) a=b;} //} template<class T> inline T low_bit(T x) {return x & -x;} /*****************************************************************/ int buf[4][4]; struct Mat{ int a[4][4]; void turnright(){ for (int i = 0 ; i < 4 ; ++i) for (int j = 0 ; j < 4 ; ++j) buf[3 - j][i] = a[i][j]; for (int i = 0 ; i < 4 ; ++i) for (int j = 0 ; j < 4 ; ++j) a[i][j] = buf[i][j]; } bool up(const Mat & A){ for (int i = 0 ; i < 4 ; ++i) if (a[0][i] != A.a[3][i]) return false; return true; } bool down(const Mat & A){ for (int i = 0 ; i < 4 ; ++i) if (a[3][i] != A.a[0][i]) return false; return true; } bool right(const Mat & A){ for (int i = 0 ; i < 4 ; ++i) if (a[i][3] != A.a[i][0]) return false; return true; } bool left(const Mat & A){ for (int i = 0 ; i < 4 ; ++i) if (a[i][0] != A.a[i][3]) return false; return true; } void input(){ for(int i = 0 ;i < 4 ; ++i) for (int j = 0 ; j < 4 ; ++j) scanf("%d" , &a[i][j]); } void output(){ for(int i = 0 ;i < 4 ; ++i){ for (int j = 0 ; j < 4 ; ++j) printf("%d " , a[i][j]); puts(""); } } }a[9][4]; int ans[3][3][2]; bool can[9][9]; int cnt[9]; bool use[9]; #define FR(A , B , C , D) for (ans[A][B][C] = 0 ; ans[A][B][C] < D ; ++ans[A][B][C]) #define aa(a , b , c) (ans[a][b][c]) #define uu(p , q) (use[ans[p][q][0]]) #define mm(p , q) (a[aa(p , q , 0)][aa(p , q , 1)]) void update(int &x , int &y , int z){ if (cnt[z] < 0) return; if (x > cnt[z]){ x = cnt[z]; y = z; } } int ds[19][19]; bool check(){ RST(can); // if (aa(0 , 1 , 0) == 1 && aa(0 , 1 , 1) == 0) // if (aa(1 , 0 , 0) == 3 && aa(1 , 0 , 1) == 0) // if (aa(1 , 2 , 0) == 5 && aa(1 , 2 , 1) == 0) // if (aa(2 , 1 , 0) == 7 && aa(2 , 1 , 1) == 0) // puts("Nice"); for (int i = 0 ; i < 9 ; ++i) if (!use[i]){ for (int j = 0 ; j < 4 ; ++j) { if (a[i][j].down(mm(1 , 0)) && a[i][j].right(mm(0 , 1))) can[0][i] = 1; if (a[i][j].up(mm(1 , 0)) && a[i][j].right(mm(2 , 1))) can[6][i] = 1; if (a[i][j].left(mm(0 , 1)) && a[i][j].down(mm(1 , 2))) can[2][i] = 1; if (a[i][j].left(mm(2 , 1)) && a[i][j].up(mm(1 , 2))) can[8][i] = 1; if (a[i][j].left(mm(1 , 0)) && a[i][j].up(mm(0 , 1)) && a[i][j].down(mm(2 , 1)) && a[i][j].right(mm(1 , 2))) can[4][i] = 1; } } RST(cnt); for (int i = 0; i < 9 ; ++i){ if (can[0][i]) ++cnt[0]; if (can[2][i]) ++cnt[2]; if (can[4][i]) ++cnt[4]; if (can[6][i]) ++cnt[6]; if (can[8][i]) ++cnt[8]; } for (int i = 0; i < 5 ;++i){ int imin = 1000 , id = 0; update(imin , id , 0); update(imin , id , 2); update(imin , id , 4); update(imin , id , 6); update(imin , id , 8); if (imin <= 0) return false; cnt[id] = -1; int chose = 0; while(!can[id][chose]) ++chose; ans[id / 3][id % 3][0] = chose; if (can[0][chose]){ can[0][chose] = 0; --cnt[0]; } if (can[2][chose]){ can[2][chose] = 0; --cnt[2]; } if (can[6][chose]){ can[6][chose] = 0; --cnt[6]; } if (can[8][chose]){ can[8][chose] = 0; --cnt[8]; } if (can[4][chose]){ can[4][chose] = 0; --cnt[4]; } } /* if (a[i][j].down(mm(1 , 0)) && a[i][j].right(mm(0 , 1))) can[0][i] = 1; if (a[i][j].up(mm(1 , 0)) && a[i][j].right(mm(2 , 1))) can[6][i] = 1; if (a[i][j].left(mm(0 , 1)) && a[i][j].down(mm(1 , 2))) can[2][i] = 1; if (a[i][j].left(mm(2 , 1)) && a[i][j].up(mm(1 , 2))) can[8][i] = 1; */ FR(0 , 0 , 1 , 4) if (mm(0 , 0).down(mm(1 , 0)) && mm(0 , 0).right(mm(0 , 1))) break; FR(0 , 2 , 1 , 4) if (mm(0 , 2).down(mm(1 , 2)) && mm(0 , 2).left(mm(0 , 1))) break; FR(2 , 0 , 1 , 4) if (mm(2 , 0).up(mm(1 , 0)) && mm(2 , 0).right(mm(2 , 1))) break; FR(2 , 2 , 1 , 4) if (mm(2 , 2).left(mm(2 , 1)) && mm(2 , 2).up(mm(1 , 2))) break; FR(1 , 1 , 1 , 4) if (mm(1 , 1).left(mm(1 , 0)) && mm(1 , 1).up(mm(0 , 1)) && mm(1 , 1).down(mm(2 , 1)) && mm(1 , 1).right(mm(1 , 2))) break; for (int i = 0 ; i < 3 ; ++i) for (int j = 0 ; j < 3 ; ++j){ for (int x = 0 ; x < 4 ; ++x) for (int y = 0 ; y < 4 ; ++y) ds[i * 3 + x][j * 3 + y] = mm(i , j).a[x][y]; } for(int i = 0 ; i < 10 ; ++i){ for(int j = 0 ; j < 10 ; ++j){ if (j) printf(" "); printf("%d" , ds[i][j]); } puts(""); } //#define debug #ifdef debug for (int i = 0 ; i < 3 ; ++i){ for (int j = 0 ; j < 3 ; ++j) printf("%d,%d " , aa(i , j , 0) , aa(i , j , 1)); puts(""); } for (int i = 0 ; i < 3 ; ++i){ for (int j = 0 ; j < 3 ; ++j){ printf("[%d %d]\n" , i , j); mm(i , j).output(); } } #endif // debg return true; } int main(){ // freopen("1.in" , "r", stdin); // freopen("1.out" , "w" , stdout); for (int i = 0 ; i < 9 ; ++i){ a[i][0].input(); for(int j = 1 ; j < 4 ; ++j){ a[i][j] = a[i][j - 1]; a[i][j].turnright(); } } RST(use); FR(0 , 1 , 0 , 9) FR(0 , 1 , 1 , 4){ uu(0 , 1) = 1; // printf("enum [%d][%d]\n" , aa(0 , 1 , 0) , aa(0 , 1 , 1)); // printf("%d -1 -1 -1\n" , aa(0 , 1 , 0) , aa(1 , 0 , 0) , aa(1 , 2 , 0) , aa(2 , 1 , 0)); // for(int i = 0 ; i < 9 ; ++i) // printf("%d " , use[i]); // puts(""); FR(1 , 0 , 0 , 9) if (!uu(1 , 0)){ // printf(">>>> %d -1 -1 -1\n" , aa(0 , 1 , 0) , aa(1 , 0 , 0) , aa(1 , 2 , 0) , aa(2 , 1 , 0)); // mm(0 , 1).output(); FR(1 , 0 , 1 , 4) { // printf("See %d %d\n", aa(1 , 0 , 0) , aa(1 , 0 , 1)); // mm(1,0).output(); if (mm(0 , 1).a[3][0] == mm(1 , 0).a[0][3]){ // printf("%d %d -1 -1\n" , aa(0 , 1 , 0) , aa(1 , 0 , 0) , aa(1 , 2 , 0) , aa(2 , 1 , 0)); uu(1 , 0) = 1; FR(1 , 2 , 0 , 9) if (!uu(1 , 2)) FR(1 , 2 , 1 , 4) if (mm(1 , 2).a[0][0] == mm(0 , 1).a[3][3]){ // printf("%d %d %d -1\n" , aa(0 , 1 , 0) , aa(1 , 0 , 0) , aa(1 , 2 , 0) , aa(2 , 1 , 0)); uu(1 , 2) = 1; FR(2 , 1 , 0 , 9) if (!uu(2 , 1)) FR(2 , 1 , 1 , 4) if (mm(2 , 1).a[0][0] == mm(1 , 0).a[3][3] && mm(2 , 1).a[0][3] == mm(1 , 2).a[3][0]){ uu(2 , 1) = 1; // printf("%d %d %d %d\n" , aa(0 , 1 , 0) , aa(1 , 0 , 0) , aa(1 , 2 , 0) , aa(2 , 1 , 0)); if (check()) return 0; uu(2 , 1) = 0; } uu(1 , 2) = 0; } uu(1 , 0) = 0; } } } // printf(">>enum [%d][%d]\n" , aa(0 , 1 , 0) , aa(0 , 1 , 1)); uu(0 , 1) = 0; } return 0; }