题目链接:http://poj.org/problem?id=1176
题意:给一排灯,初始是开着的。现在有四种开关方式,要求某些灯不准开某些灯不准关,给定操作次数,问经过这些次操作后合法的情况有多少种。
考虑开关方式有四种,每种奇数次才会达到效果,偶数次相当于没有操作,因此总操作可以化简为<=4次,因此最大的操作数实际上是4^4种。只需要把操作数在0~4中等效一下,回溯一下模拟就行了。
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <cassert> 8 #include <cstdio> 9 #include <bitset> 10 #include <vector> 11 #include <deque> 12 #include <queue> 13 #include <stack> 14 #include <ctime> 15 #include <set> 16 #include <map> 17 #include <cmath> 18 using namespace std; 19 20 const int maxn = 110; 21 int n, c; 22 int on[maxn], of[maxn]; 23 int st[maxn]; 24 set<string> ret; 25 26 void b1() { for(int i = 1; i <= 100; i++) st[i] ^= 1; } 27 void b2() { for(int i = 1; i <= 100; i+=2) st[i] ^= 1; } 28 void b3() { for(int i = 2; i <= 100; i+=2) st[i] ^= 1; } 29 void b4() { for(int i = 1; i <= 100; i+=3) st[i] ^= 1; } 30 31 bool ok() { 32 for(int i = 1; i <= n; i++) { 33 if(on[i] && !st[i]) return 0; 34 if(of[i] && st[i]) return 0; 35 } 36 return 1; 37 } 38 39 void dfs(int cnt) { 40 if(cnt == c) { 41 if(!ok()) return; 42 string tmp = ""; 43 for(int i = 1; i <= n; i++) tmp += st[i] + '0'; 44 ret.insert(tmp); 45 return; 46 } 47 b1(); dfs(cnt+1); b1(); 48 b2(); dfs(cnt+1); b2(); 49 b3(); dfs(cnt+1); b3(); 50 b4(); dfs(cnt+1); b4(); 51 } 52 53 int main() { 54 // freopen("in", "r", stdin); 55 int x; 56 while(~scanf("%d%d",&n,&c)) { 57 memset(on, 0, sizeof(on)); 58 memset(of, 0, sizeof(of)); 59 ret.clear(); 60 for(int i = 1; i <= 100; i++) st[i] = 1; 61 while(~scanf("%d", &x) && x != -1) on[x] = 1; 62 while(~scanf("%d", &x) && x != -1) of[x] = 1; 63 if(c > 4) { 64 if(c & 1) c = 3; 65 else c = 4; 66 } 67 dfs(0); 68 for(set<string>::iterator it = ret.begin(); it != ret.end(); it++) { 69 cout << *it << endl; 70 } 71 } 72 return 0; 73 }