http://codeforces.com/gym/100650
阅读题,边界的cell的邻居要当成一个环形的来算,时间有8s,状态最多2^16种,所以直接暴力枚举就行了。另外一种做法是逆推。
#include<bits/stdc++.h> using namespace std; int m,n; const int maxn = 17; int g[maxn][maxn]; int cnt[maxn][maxn]; int dx[] = {-1,1,-1,-1, 1,1,0, 0}; int dy[] = { 0,0,-1, 1,-1,1,1,-1}; typedef pair<int,int> pii; #define fi first #define se second #define PB push_back #define MP make_pair int tar; bool check(int mask) { for(int i = 0; i < m; i++) for(int j = 0; j < n; j++){ g[i][j] = (mask>>(i*n+j))&1; } vector<pii> die,birth; for(int i = 0; i < m; i++) for(int j = 0; j < n; j++){ cnt[i][j] = 0; for(int k = 0; k < 8; k++){ int nx = i+dx[k],ny = j+dy[k]; if(nx>=m) nx = 0; if(nx<0) nx = m-1; if(ny<0) ny = n-1; if(ny>=n) ny = 0; cnt[i][j] += g[nx][ny]; } if(cnt[i][j]<2||cnt[i][j]>=4) die.PB(MP(i,j)); if(!g[i][j] && cnt[i][j] == 3) birth.PB(MP(i,j)); } for(int i = 0; i < die.size(); i++) { pii &t = die[i]; g[t.fi][t.se] = 0; } for(int i = 0; i < birth.size(); i++){ pii &t = birth[i]; g[t.fi][t.se] = 1; } int sta = 0; for(int i = 0; i < m; i++){ for(int j = 0; j < n; j++){ if(g[i][j]) sta |= 1<<(i*n+j); } } return sta == tar; } int main() { // freopen("in.txt","r",stdin); int kas = 0; while(~scanf("%d%d",&m,&n)&&m){ if(kas++) putchar(' '); int N; scanf("%d",&N); tar = 0; while(N--){ int r,c; scanf("%d%d",&r,&c); tar |= 1<<(r*n+c); } int M = 1<<(n*m); int ans = 0; for(int mask = 0; mask < M; mask++){ ans += check(mask); } printf("Case %d: ",kas); if(ans) printf("%d possible ancestors.",ans); else printf("Garden of Eden."); } return 0; }