您的位置:首页 > 其它

BZOJ 1026 [SCOI2009]windy数【数位DP】

2016-07-19 08:29 465 查看

题目链接:

http://www.lydsy.com/JudgeOnline/problem.php?id=1026

题意:

windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,

在A和B之间,包括A和B,总共有多少个windy数?

分析:

比较基础的数位dp,

设dp[i][j][k][m],其中k标记是否与原数相等,m标记是否全为0,因为如果前面全为0的话,那么这一位可以放任何数。表示进行到第i位,数字为j的数一共有多少种,两个数做个差即可。

代码:

/*************************************************************************
> File Name: 1026.cpp
> Author: jiangyuzhu
> Mail: 834138558@qq.com
> Created Time: 2016/7/18 20:52:36
************************************************************************/

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
using namespace std;
const int maxn = 10 + 5;
int dp[maxn][maxn][2][2];
char s[maxn];
int a[maxn];
int len;
int solve(char *s)
{
len = strlen(s);
for(int i = 0; i < len; i++){
a[i] = s[i] - '0';
}
for(int i = 1; i < a[0]; i++){
dp[0][i][1][1] = 1;
}
dp[0][a[0]][0][1] = 1;
dp[0][0][1][0] = 1;// 全为0
for(int i = 1; i < len; i++){
if(abs(a[i] - a[i - 1]) >= 2) dp[i][a[i]][0][1] = dp[i - 1][a[i - 1]][0][1];
for(int j = 0; j < 10; j++){
for(int k = 0; k < 10; k++){
if(k == 0){
if(j == 0) dp[i][j][1][0] += dp[i - 1][k][1][0];
else dp[i][j][1][1] += dp[i - 1][k][1][0];
}
if(abs(j - k) >= 2)  dp[i][j][1][1] += dp[i - 1][k][1][1];
}
if(j < a[i] && abs(j - a[i - 1]) >= 2)
dp[i][j][1][1] += dp[i - 1][a[i - 1]][0][1];
}
}
int ans = 0;
for(int i = 0; i < 10; i++){
ans += dp[len - 1][i][1][1];
}
return ans;
}
int main (void)
{
scanf("%s", s);
int ans = solve(s);
memset(dp, 0, sizeof(dp));
memset(a, 0, sizeof(a));
scanf("%s", s);
int ans1 = dp[len - 1][a[len - 1]][0][1] + solve(s);
printf("%d\n", ans1 - ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: