HDU 5965 扫雷
这种题乍一看都是整体性非常的强,有每一步都有很多种情况,但是又必须要为结果的成功作铺垫,这样直接分析的话确实很复杂。
因为一共只有三行,那么从最左边的一列开始分析,这一列可以填的雷可以有0,1,2对应的方案数分别是1,2,1,那么如果第一列确定了,那么第二列
根据第一列第二行已经有的数据,也确定了,如此发现就是当第一列的状态确定那么整个序列就可以确定,至于方案的成功与否只需要检测
在过程中间推导是否有矛盾,和最后一列的情况是否符合。
这种确定一个状态,整个系统状态就大体确定的,符合开关问题,因此只需要枚举第一列填的个数即可。
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <queue> 5 #include <vector> 6 #include <algorithm> 7 #include <stack> 8 #include <set> 9 #include <map> 10 #include <math.h> 11 #define pb push_back 12 #define CLR(a) memset(a, 0, sizeof(a)); 13 #define MEM(a, b) memset(a, b, sizeof(a)); 14 #define fi first 15 #define se second 16 17 using namespace std; 18 19 typedef long long ll; 20 21 const int MAXN = 10007; 22 const int MAXV = 207; 23 const int MAXE = 207; 24 const int INF = 0x3f3f3f3f; 25 const ll MOD = 1e8+7; 26 27 char s[MAXN]; 28 29 int a[MAXN]; 30 ll vars[3] = {1, 2, 1}; 31 ll ans = 0; 32 int t[MAXN]; 33 int len; 34 ll solve() 35 { 36 ll ret = 0; 37 for (int i = 1; i < len; i++) 38 { 39 if (i == 1 && (a[i-1] < t[i-1] || (t[i-1] + 2) < a[i-1]) ) return 0; 40 else if (i != 1 && (a[i-1] < (t[i-1]+t[i-2]) || (t[i-2]+t[i-1]+2) < a[i-1])) return 0; 41 if (i == 1) t[i] = a[i-1] - t[i-1]; 42 else t[i] = a[i-1] - t[i-1] - t[i-2]; 43 } 44 if (len == 1 && t[0] != a[0]) return 0; 45 if (t[len-1]+t[len-2] != a[len-1]) return 0; 46 ret = vars[t[0]]; 47 for (int i = 1; i < len; i++) 48 { 49 ret = (ret * vars[t[i]]) % MOD; 50 } 51 return ret % MOD; 52 } 53 54 55 int main() 56 { 57 //freopen("in.txt", "r", stdin); 58 int T; 59 scanf("%d", &T); 60 while (T--) 61 { 62 scanf("%s", s); 63 len = strlen(s); 64 for (int i = 0; i < len; i++) 65 a[i] = s[i] - '0'; 66 ans = 0; 67 for (int i = 0; i < 3; i++) 68 { 69 t[0] = i; 70 ll tmp = solve(); 71 //cout << tmp << endl; 72 ans = (ans + tmp) % MOD; 73 // cout << i << " " << ans << endl; 74 } 75 cout << ans << endl; 76 } 77 return 0; 78 }