• 【动态规划】【记忆化搜索】hdu5965 扫雷


    f(i,j,k)表示第i行,放的雷的状态为j{0表示不放,1表示往上放,2表示往下放,3表示上下都放},剩余还有k(0<=k<=2)个要放的方案数。

    先给出我这个sb写的错误代码,死都没调出来。优越的做法在后面

    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define MOD 100000007
    int T,n;
    char a[10010];
    int f[10010][4][10];
    int main(){
    	scanf("%d",&T);
    	for(;T;--T){
    		scanf("%s",a+1);
    		n=strlen(a+1);
    		a[0]='0';
    		memset(f,0,sizeof(f));
    		f[1][0][a[1]-'0']=1;
    		if(a[1]-'0'-1>=0){
    			f[1][1][a[1]-'0'-1]=1;
    		}
    		if(a[1]-'0'-1>=0){
    			f[1][2][a[1]-'0'-1]=1;
    		}
    		if(a[1]-'0'-2>=0){
    			f[1][3][a[1]-'0'-2]=1;
    		}
    		for(int i=1;i<n;++i){
    			for(int j=a[i]-'0';j>=a[i]-'0'-2 && j>=0;--j){
    				if(j<=2 && j+0<=a[i+1]-'0'){
    					if(j==0){
    						f[i+1][0][a[i+1]-'0']=(f[i+1][0][a[i+1]-'0']+f[i][0][0])%MOD;
    					}
    					else if(j==1){
    						f[i+1][1][a[i+1]-'0'-1]=(f[i+1][1][a[i+1]-'0'-1]+f[i][0][1])%MOD;
    						f[i+1][2][a[i+1]-'0'-1]=(f[i+1][2][a[i+1]-'0'-1]+f[i][0][1])%MOD;
    					}
    					else{
    						f[i+1][3][a[i+1]-'0'-2]=(f[i+1][3][a[i+1]-'0'-2]+f[i][0][2])%MOD;
    					}
    				}
    			}
    			for(int j=a[i]-'0'-1;j>=a[i]-'0'-2-1 && j>=0;--j){
    				if(j<=2 && j+1<=a[i+1]-'0'){
    					if(j==0){
    						f[i+1][0][a[i+1]-'0'-1]=(f[i+1][0][a[i+1]-'0'-1]+f[i][1][0])%MOD;
    					}
    					else if(j==1){
    						f[i+1][1][a[i+1]-'0'-2]=(f[i+1][1][a[i+1]-'0'-2]+f[i][1][1])%MOD;
    						f[i+1][2][a[i+1]-'0'-2]=(f[i+1][2][a[i+1]-'0'-2]+f[i][1][1])%MOD;
    					}
    					else{
    						f[i+1][3][a[i+1]-'0'-3]=(f[i+1][3][a[i+1]-'0'-3]+f[i][1][2])%MOD;
    					}
    				}
    			}
    			for(int j=a[i]-'0'-1;j>=a[i]-'0'-2-1 && j>=0;--j){
    				if(j<=2 && j+1<=a[i+1]-'0'){
    					if(j==0){
    						f[i+1][0][a[i+1]-'0'-1]=(f[i+1][0][a[i+1]-'0'-1]+f[i][2][0])%MOD;
    					}
    					else if(j==1){
    						f[i+1][1][a[i+1]-'0'-2]=(f[i+1][1][a[i+1]-'0'-2]+f[i][2][1])%MOD;
    						f[i+1][2][a[i+1]-'0'-2]=(f[i+1][2][a[i+1]-'0'-2]+f[i][2][1])%MOD;
    					}
    					else{
    						f[i+1][3][a[i+1]-'0'-3]=(f[i+1][3][a[i+1]-'0'-3]+f[i][2][2])%MOD;
    					}
    				}
    			}
    			for(int j=a[i]-'0'-2;j>=a[i]-'0'-2-2 && j>=0;--j){
    				if(j<=2 && j+2<=a[i+1]-'0'){
    					if(j==0){
    						f[i+1][0][a[i+1]-'0'-2]=(f[i+1][0][a[i+1]-'0'-2]+f[i][3][0])%MOD;
    					}
    					else if(j==1){
    						f[i+1][1][a[i+1]-'0'-3]=(f[i+1][1][a[i+1]-'0'-3]+f[i][3][1])%MOD;
    						f[i+1][2][a[i+1]-'0'-3]=(f[i+1][2][a[i+1]-'0'-3]+f[i][3][1])%MOD;
    					}
    					else{
    						f[i+1][3][a[i+1]-'0'-4]=(f[i+1][3][a[i+1]-'0'-4]+f[i][3][2])%MOD;
    					}
    				}
    			}
    		}
    		printf("%d
    ",f[n][0][0]+f[n][1][0]+f[n][2][0]+f[n][3][0]);
    	}
    	return 0;
    }
    

    然后是斓爷优越的记忆化搜索

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    long long use[11000][3][3],dp[11000][3][3],qw,wq,l;
    char s[11000];
    long long mo=100000007;
    long long num[3]={1,2,1};
    long long getans(long long d,long long a,long long b)
    {
        if (d>l)
        {
            if (b!=0) return 0;
            return 1;
        }
        if (b>2 || a+b>s[d-1]-48) return 0;
        if (use[d][a][b]==qw) return dp[d][a][b];
        use[d][a][b]=qw;
        dp[d][a][b]=getans(d+1,b,s[d-1]-48-a-b)*num[b]%mo;
        return dp[d][a][b];
    }
    
    int main()
    {
        scanf("%lld",&wq);
        for (qw=1;qw<=wq;qw++)
        {
            scanf("%s",&s);
            l=strlen(s);
            printf("%lld
    ",(getans(1,0,0)+getans(1,0,1)+getans(1,0,2))%mo);
        }
    }
    
  • 相关阅读:
    AM8 自定义表情包的实现方法
    Create STKNetDiskC Instance Error
    怎样实现文件发文功能
    企业云盘的数据备份
    一种可行的文档协同编辑方法实现
    【OI】二分图最大匹配
    【OI】位运算操作
    【OI】关于快速幂的简单理解
    【OI】线性筛
    【OI】指针线段树&指针
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/6920825.html
Copyright © 2020-2023  润新知