您的位置:首页 > 其它

HDU 5787 K-wolf Number(数位DP)

2016-08-02 20:41 351 查看
题目链接:点击打开链接

思路:

我们用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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm-icpc HDU 数位DP