Generating Polynomino in C++
http://en.wikipedia.org/wiki/Polyomino
one-handedなもの。つまり回転による同型は無視する。また、穴があるものはなしとする。
#include <iostream> #include <iomanip> #include <vector> #include <map> #include <set> #include <queue> #include <bitset> #include <stack> #include <utility> #include <numeric> #include <algorithm> #include <functional> #include <complex> #include <string> #include <sstream> #include <cstdio> #include <cstdlib> #include <cctype> #include <cstring> using namespace std; template<typename T> ostream& operator<<(ostream& os,const vector<T>& val){ os << "[ "; for(typename vector<T>::const_iterator it=val.begin(); it != val.end();++it){ os << *it << " "; } os << "]"; return os; } struct Block{ int x,y; Block(int _x,int _y) : x(_x),y(_y) {} // 0 1 2 3 4 inline Block rotate() const{ return Block(-y,x); } inline Block shift(const int &dx, const int &dy) const{ return Block(x+dx,y+dy); } bool operator<(const Block& rhs) const{ if(x != rhs.x) return x < rhs.x; else return y < rhs.y; } bool operator==(const Block& rhs) const{ return x == rhs.x and y == rhs.y; } }; ostream& operator<<(ostream& os,const Block& b){ os << "(" << b.x << "," << b.y << ")"; return os; } ostream& operator<<(ostream& os,const set<Block>& b){ os << "["; for(const auto& a : b){ os << a << ","; } os << "]"; return os; } set<Block> rotate_block(const set<Block>& base){ set<Block> new_blocks; for(const auto& b : base){ new_blocks.insert(b.rotate()); } return new_blocks; } set<Block> regularize_block(const set<Block>& base){ int mx = 1<<30,my=1<<30; for(const auto& b : base){ mx = min(mx,b.x); my = min(my,b.y); } set<Block> new_blocks; for(const auto& b : base){ new_blocks.insert(b.shift(-mx,-my)); } return new_blocks; } const vector<int> dx = {1,0,-1,0}; const vector<int> dy = {0,1,0,-1}; void generate_blocks(const size_t& n,const set<Block>& base, set<set<Block>>& S){ if(base.size() == n) return; for(const auto& b : base){ for(size_t i=0;i<min(dx.size(),dy.size());i++){ Block new_block(b.x+dx[i],b.y+dy[i]); if(base.find(new_block) != base.end()) continue; set<Block> new_base = base; new_base.insert(new_block); new_base = regularize_block(new_base); bool is_new = true; for(int j=0;j<4;j++){ is_new = is_new and (S.find(new_base) == S.end()); new_base = rotate_block(new_base); new_base = regularize_block(new_base); } new_base = rotate_block(new_base); new_base = regularize_block(new_base); if(is_new){ S.insert(new_base); generate_blocks(n,new_base,S); } } } return; } int main(){ set<set<Block>> S; Block root(0,0); S.insert({root}); const int N = 10; generate_blocks(N,{root},S); vector<vector<set<Block>>> bs(N+1); int cnt = 0; for(const auto& b : S){ bs[b.size()].push_back(b); } for(const auto& b : bs){ cout << b.size() << endl; } cerr << cnt << endl; return 0; }