ccpc合肥站的重现...一看就觉得是dp 然后强行搞出来一个转移方程 即 根据第i-1列的需求和i-1 i-2列的枚举摆放 可以得出i列摆放的种类..加了n多if语句...最后感觉怎么都能过了..然而不是t就是wa..最后看别人的题解 我的dp转移是9*O(n)的 常数要t..
别人的题解居然都是用模拟的..根据枚举第一列可以得出第二列的摆放姿势 由这两个摆放和第二列的需求可以求出来第三列..以此类推 最后check一下最后两个..
叉姐的题解里面写了一个dp转移方程..然而并不能看懂..放牛说用状压搞一发就行...有空再补吧..
枚举第一列的模拟版本
#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> #include<map> #include<iostream> #include<string> #include<vector> using namespace std; #define L long long char s[10050]; L a[10050]; L b[10050]; L d(L a){ if(a == 1){ return 2; } else { return 1; } } const L mod = 100000007; int main(){ int t; scanf("%d",&t); while(t--){ scanf("%s",s); int len = strlen(s); for(int i=1;i<=len;i++){ a[i] = s[i - 1] - '0'; } if(len == 1){ if(a[1] == 1){ printf("2 "); } else if(a[1]==0 || a[1] == 2){ printf("1 "); } else { printf("0 "); } continue; } L ans = 0; for(L i=0;i<=2;i++){ /// 枚举第一列放多少 b[1] = i; b[2] = a[1] - i; L sum = d(b[1])*d(b[2]); /// 初始状态的种数 if(b[2] < 0 || b[2] > 2)continue; for(int j=3;j<=len;j++){ b[j] = a[j - 1] - b[j - 1] - b[j - 2]; if(b[j] < 0 || b[j] > 2){ sum = 0; break; } sum *= d(b[j]); sum %= mod; } if(b[len] + b[len-1] != a[len]){ sum = 0; } ans += sum; ans %= mod; } printf("%lld ",ans); } }