Gym - 101889E Enigma(数位填数+记忆化)

https://cn.vjudge.net/problem/Gym-101889E

 

1??????????????????????????????? 2

10000000000000000000000000000000

 

???????????????????????????????1 2

*

 

?294?? 17

129404

 

 

题意:给出一个数(长度<=1000),某些数位未知,向?填数,使其能被MOD(<=1000)整除且最小(不含前导零)。

利用数位dp思想,从前往后从小到大依次填数,dp[pos][sta]标记当前状态。

往常的数位dp大多表示方案数,这里只需用01表示该状态是否出现过即可,因此便达到了记忆化的效果。

找到的第一个满足条件的数即为最小。

 

#include <bits/stdc++.h>
#define MAX 1005
using namespace std;
typedef long long ll;

int len,MOD;
string s;
int dp[MAX][MAX];
int f;
inline void dfs(int pos,int sta,string ans){
    if(f==1) return;
    if(pos==len){
        if(sta==0){
            f=1;
            cout<<ans<<endl;
        }
        return;
    }
    if(dp[pos][sta]==1) return;
    if(s[pos]=='?'){
        for(int i=0;i<=9;i++){
            if(pos==0&&i==0) continue;
            if(f==1) return;
            dfs(pos+1,(sta*10+i)%MOD,ans+(char)(i+'0'));
            if(f==1) return;
        }
    }
    else{
        if(f==1) return;
        dfs(pos+1,(sta*10+s[pos]-'0')%MOD,ans+s[pos]);
        if(f==1) return;
    }
    dp[pos][sta]=1;
}
int main(void)
{
    cin>>s>>MOD;
    f=0;len=s.length();
    dfs(0,0,"");
    if(f==0) cout<<"*"<<endl;
    return 0;
}

 

posted @ 2018-10-03 21:27  yzm10  阅读(298)  评论(0编辑  收藏  举报