首页 > 代码库 > HDU 5965 枚举模拟 + dp(?)

HDU 5965 枚举模拟 + dp(?)

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\n");
            }
            else if(a[1]==0 || a[1] == 2){
                printf("1\n");
            }
            else {
                printf("0\n");
            }
            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\n",ans);
    }
}

  

HDU 5965 枚举模拟 + dp(?)