码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5787 K-wolf Number(数位DP)

时间:2016-08-02 21:11:55      阅读:389      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:点击打开链接

思路:

我们用dp[cur][a][b][c][d][p]表示当前到了第cur位,前四位分别是abcd并且当前是否已经小于给定的数的方案数。  我们分别算出L和R的dp值,  以及L是否符合要求, 做差并把多减的加上即可。  比赛时写的比较恶心, 不是很美观但是很直观。

细节参见代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const double PI = acos(-1);
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 11;
int n, m, v,cnt= 0, sum[maxn];
ll L, R, B[33], C[33], dp[19][maxn][maxn][maxn][maxn][2], vis[19][maxn][maxn][maxn][maxn][2];
int k, kase = 0, q, id;
ll dp1(int cur, int a, int b, int c, int d, int p) {
    ll& ans = dp[cur][a][b][c][d][p];
    if(cur == cnt) return 1LL;
    if(vis[cur][a][b][c][d][p] == kase) return ans;
    vis[cur][a][b][c][d][p] = kase;
    ans = 0;
    if(p) {
        for(int i = 0; i < 10; i++) {
            if(k == 2) {
                if(d == i) continue;
            }
            else if(k == 3) {
                if(c == i || d == i) continue;
            }
            else if(k == 4) {
                if(b == i || c == i || d == i) continue;
            }
            else {
                if(a == i || b == i || c == i || d == i) continue;
            }
            if(i == 0) {
                if(d == 10) ans += dp1(cur+1, a, b, c, d, p);
                else ans += dp1(cur+1, b, c, d, i, p);
            }
            else ans += dp1(cur+1, b, c, d, i, p);
        }
    }
    else {
        for(int i = 0; i < 10; i++) {
            if(k == 2) {
                if(d == i) continue;
            }
            else if(k == 3) {
                if(c == i || d == i) continue;
            }
            else if(k == 4) {
                if(b == i || c == i || d == i) continue;
            }
            else {
                if(a == i || b == i || c == i || d == i) continue;
            }
            if(i < B[cur]) {
                if(i == 0) {
                    if(d == 10) ans += dp1(cur+1, a, b, c,d, 1);
                    else ans += dp1(cur+1, b, c,d, i, 1);
                }
                else ans += dp1(cur+1, b, c,d, i, 1);
            }
            else if(i == B[cur]) {
                if(i == 0) {
                    if(d == 10) ans += dp1(cur + 1, a, b, c, d, p);
                    else ans += dp1(cur+1, b, c, d, i, p);
                }
                else ans += dp1(cur+1, b, c, d, i, p);
            }
        }
    }
    return ans;
}
bool ok() {
    for(int i = 0; i < cnt; i++) {
        for(int j = i-1; j >= max(0, i-(k-1)); j--) {
            if(B[j] == B[i]) return false;
        }
    }
    return true;
}
int main() {
    while(~scanf("%I64d%I64d%d", &L, &R, &k)) {
        ++kase;
        ll cur = R;
        int cc = 0; cnt = 0;
        while(cur) {
            C[cc++] = cur % 10;
            cur /= 10;
        }
        for(int i = cc-1; i >= 0; i--) {
            B[cnt++] = C[i];
        }
        ll ans1 = dp1(0, 10, 10, 10, 10, 0);
        cc = 0; cnt = 0;
        cur = L;
        while(cur) {
            C[cc++] = cur % 10;
            cur /= 10;
        }
        for(int i = cc-1; i >= 0; i--) B[cnt++] = C[i];
        ++kase;
        ll ans2 = dp1(0, 10, 10, 10, 10, 0);
        if(ok()) printf("%I64d\n", ans1 - ans2 + 1);
        else printf("%I64d\n", ans1 - ans2);
    }
    return 0;
}


HDU 5787 K-wolf Number(数位DP)

标签:

原文地址:http://blog.csdn.net/weizhuwyzc000/article/details/52097690

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!