动态规划晋级——HDU 3555 Bomb【数位DP详解】
2013-10-09 09:19
639 查看
hdu3555 Bomb
2012-07-12 19:37 372人阅读 评论(1) 收藏 举报integerinputoutputtrainingnumberseach
Bomb
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 1604 Accepted Submission(s): 592
Problem Description
The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the time bomb. The number sequence of the time bomb counts from 1 to N. If the current number sequence includes the sub-sequence "49", the power of the blast would
add one point.
Now the counter-terrorist knows the number N. They want to know the final points of the power. Can you help them?
Input
The first line of input consists of an integer T (1 <= T <= 10000), indicating the number of test cases. For each test case, there will be an integer N (1 <= N <= 2^63-1) as the description.
The input terminates by end of file marker.
Output
For each test case, output an integer indicating the final points of the power.
Sample Input
3 1 50 500
Sample Output
0 1 15 HintFrom 1 to 500, the numbers that include the sub-sequence "49" are "49","149","249","349","449","490","491","492","493","494","495","496","497","498","499", so the answer is 15.
Author
fatboy_cw@WHU
Source
2010
ACM-ICPC Multi-University Training Contest(12)——Host by WHU
Recommend
zhouzeyong
顺便写道数位dp的题,直接dfs下去就可以了,没什么说的。
[cpp] view
plaincopy
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int dig[20];
long long dp[20][2][12];
long long F(int pos,bool have,int last,bool inf)
{
int i;
if (pos==-1) return have;
if (!inf && dp[pos][have][last]!=-1) return dp[pos][have][last];
int end=inf?dig[pos]:9;
long long ans=0;
for (i=0;i<=end;i++)
{
if (last==4 && i==9) ans+=F(pos-1,true,i,inf && (i==end));
else ans+=F(pos-1,have,i,inf && (i==end));
}
if (!inf)
{
dp[pos][have][last]=ans;
}
return ans;
}
long long Cal(long long t)
{
int i,j,pos=0;
while(t)
{
dig[pos++]=t%10;
t/=10;
}
return F(pos-1,0,0,1);
}
int main()
{
int i,j,T;
__int64 n;
scanf("%d",&T);
while(T--)
{
memset(dp,-1,sizeof(dp));
scanf("%I64d",&n);
printf("%I64d\n",Cal(n));
}
return 0;
}
HDU 3555 Bomb (数位DP)
分类: HDU 动态规划DP2012-08-1420:24 466人阅读 评论(1) 收藏 举报
做的第一道数位DP啊!开始在找规律,搜索,做了很久终于找到了规律,上网一查发现原来这样的叫数位DP。。
找到的规律就是这个样子了。有了规律就很好做了。dp[i][0]=dp[i-1][0]*10-dp[i-1][1];是因为要减去49XXX的情况。
[cpp] view
plaincopy
//Time:15MS
//Memory:488K
#include<string.h>
#include<stdio.h>
long long dp[20][3];
int num[20];
int main()
{
memset(dp,0,sizeof(dp));
dp[0][0] = 1;
for(int i = 1;i<= 20;i++){
dp[i][0]=dp[i-1][0]*10-dp[i-1][1]; //dp[i][0] 表示i位数字中不含49的数字的个数
dp[i][1]=dp[i-1][0]; //dp[i][1] 表示i位数字中以9开头的数字的个数
dp[i][2]=dp[i-1][2]*10+dp[i-1][1];//dp[i][2] 表示i位数字中含有49的数字的个数
}
int t;
scanf("%d",&t);
while(t--)
{
int len = 0,last = 0;
long long ans = 0;
long long n = 0;
scanf("%I64d",&n);
n++;
memset(num,0,sizeof(num));
while(n){
num[++len]=n%10;
n/=10;
}
bool flag=false;
for(int i=len;i>=1;i--)
{
ans+=dp[i-1][2]*num[i];
if(flag)
{
ans+=dp[i-1][0]*num[i];
}
if(!flag && num[i]>4)
{
ans+=dp[i-1][1];
}
if(last==4 && num[i]==9)
{
flag=true;
}
last=num[i];
}
printf("%I64d\n",ans);
}
}
动态规划晋级——HDU 3555 Bomb【数位DP详解】
分类: 动态规划2013-10-0816:34 80人阅读 评论(0) 收藏 举报
数位DP
转载请注明出处:http://blog.csdn.net/a1dark
分析:初学数位DP完全搞不懂、很多时候都是自己花大量时间去找规律、记得上次网络赛有道数位DP、硬是找规律给A了、那时候完全不知数位DP为何物、不过还是有很多时候要用数位DP、比如当一个数字超过了数组承受的极限、不能再打表AC、先看这道题、首先划分状态、然后初始化、最后从高位向低位状态转移、代码含详解
[cpp] view
plaincopyprint?
//dp[len][0]表示长度为len不含49的数量
//dp[len][1]表示长度为len不含44但以9开头的数字的数量
//dp[len][2]表示长度为len含有49的数量
#include<stdio.h>
#include<string.h>
__int64 dp[20][3];
int num[20];
int main(){
dp[0][0]=1;
for(int i=1;i<=20;i++){
dp[i][0]=dp[i-1][0]*10-dp[i-1][1];//要减去9开头的数
dp[i][1]=dp[i-1][0];//在不含49的数量中加9在开头
dp[i][2]=dp[i-1][2]*10+dp[i-1][1];//以前含49、这一位有10种选择+以前只含9这一位可以是4
}
int t;
scanf("%d",&t);
while(t--){
int len=1,last=0;
__int64 ans=0,n=0;
scanf("%I64d",&n);
memset(num,0,sizeof(num));
n++;
while(n>0){//用num数组来记录每一位的数字、为下面递推做准备
num[len]=n%10;
n/=10;
len++;
}
int flag=0;
for(int i=len;i>=1;i--){//从高位往低位递推
ans+=dp[i-1][2]*num[i];//如果后面含有49、那么这一位可以填1到(num[i]-1)
if(flag==1)//如果前一位挨着49
ans+=dp[i-1][0]*num[i];//那么加上这个是没问题的
if(flag==0&&num[i]>4)//如果前一位没有挨着49、但是这一位比4大
ans+=dp[i-1][1];//那么加上开头为9的是正确的、
if(last==4&&num[i]==9)//判断当前位和上一位是否能组成49
flag=1;
last=num[i];//当前位转移为上一位
}
printf("%I64d\n",ans);
}
return 0;
}
相关文章推荐
- 动态规划晋级——HDU 3555 Bomb【数位DP详解】
- 动态规划晋级——HDU 3555 Bomb【数位DP详解】
- HDU 3555 Bomb 详解(数位DP入门题)
- 【HDU】3555 Bomb 数位DP
- 数位DP-HDU-3555-Bomb
- [数位DP]Hdu 3555——Bomb
- HDU-3555 Bomb 数位DP
- HDU 3555 Bomb(基础数位dp)
- HDU 3555 Bomb (数位DP)
- hdu_3555_Bomb(数位DP)
- HDU 3555 Bomb 数位DP
- HDU 3555 Bomb(数位DP模板啊两种形式)
- Bomb(HDU 3555 数位DP)
- HDU 3555 Bomb题解(数位dp)
- HDU 3555 Bomb(数位DP)
- hdu 3555 bomb(数位dp)
- HDU 3555 Bomb (数位DP)
- hdu 3555 Bomb 数位DP
- HDU 3555 Bomb(数位DP)
- HDU 3555 Bomb (简单数位DP)