2012 TCO Algorithm Championship Round - Division I, Level Two PeriodicTiling 题解
2012 TCO Algorithm Championship Round - Division I, Level Two PeriodicTiling 题解
首先考虑所有块完全一样这个条件。
假设按照向量\(\{v_1,v_2,v_3...\}\)平移整个平面和原来的完全重合。
取这组向量的两个基\(A,B\)。
则所有的区域可以看作:
. . . .
. . . .
. . . .
. . . .
类似这样。
然后割补一下,可以发现答案恰好就是\(A,B\)的叉积。
然后只需要枚举平移向量就行了。
时间复杂度\(O(N^6)\)。
code:
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
// int x=0;
// char ch=getchar();
// while(ch<'0'||ch>'9'){
// ch=getchar();
// }
// while(ch>='0'&&ch<='9'){
// x=(x<<1)+(x<<3)+(ch^48);
// ch=getchar();
// }
// return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
vector<string> maze;
int n,m;
bool out(int x,int y){
return !(x<3*n&&x>=0&&y<3*m&&y>=0);
}
char tmp[200][200];
bool check(int xa,int ya,int xb,int yb){
rep(i,3*n) rep(j,3*m) tmp[i][j]='*';
rep(i,n) rep(j,m) tmp[i+n][j+m]=maze[i][j];
rep(i,3*n) rep(j,3*m){
if(!out(i+xa,j+ya)){
if(tmp[i][j]=='*') tmp[i][j]=tmp[i+xa][j+ya];
else if(tmp[i+xa][j+ya]=='*') tmp[i+xa][j+ya]=tmp[i][j];
else if(tmp[i+xa][j+ya]!=tmp[i][j]) return false;
}
if(!out(i+xb,j+yb)){
if(tmp[i][j]=='*') tmp[i][j]=tmp[i+xb][j+yb];
else if(tmp[i+xb][j+yb]=='*') tmp[i+xb][j+yb]=tmp[i][j];
else if(tmp[i+xb][j+yb]!=tmp[i][j]) return false;
}
if(!out(i-xa,j-ya)){
if(tmp[i][j]=='*') tmp[i][j]=tmp[i-xa][j-ya];
else if(tmp[i-xa][j-ya]=='*') tmp[i-xa][j-ya]=tmp[i][j];
else if(tmp[i-xa][j-ya]!=tmp[i][j]) return false;
}
if(!out(i-xb,j-yb)){
if(tmp[i][j]=='*') tmp[i][j]=tmp[i-xb][j-yb];
else if(tmp[i-xb][j-yb]=='*') tmp[i-xb][j-yb]=tmp[i][j];
else if(tmp[i-xb][j-yb]!=tmp[i][j]) return false;
}
}
return true;
}
class PeriodicTiling{
public:
int minBlock(vector<string> tmp){
maze=tmp;
n=maze.size();
m=maze[0].length();
int ans=INF;
rb(xa,-n,n){
rb(ya,0,m){
rb(xb,-n,xa){
rb(yb,0,m){
if(abs(xa*yb-xb*ya)&&abs(xa*yb-xb*ya)<ans&&check(xa,ya,xb,yb)){
check_min(ans,abs(xa*yb-xb*ya));
}
}
}
}
}
return ans;
}
}solver;