您的位置:首页 > 其它

POJ3252:Round Numbers(数位DP+记忆化DFS)

2013-08-18 21:41 323 查看
Description

Thecows,asyouknow,havenofingersorthumbsandthusareunabletoplayScissors,Paper,Stone'(alsoknownas'Rock,Paper,Scissors','Ro,Sham,Bo',andahostofothernames)inordertomakearbitrarydecisionssuchaswhogetstobemilkedfirst.Theycan'tevenflipacoinbecauseit'ssohardtotossusinghooves.

Theyhavethusresortedto"roundnumber"matching.Thefirstcowpicksanintegerlessthantwobillion.Thesecondcowdoesthesame.Ifthenumbersareboth"roundnumbers",thefirstcowwins,
otherwisethesecondcowwins.

ApositiveintegerNissaidtobea"roundnumber"ifthebinaryrepresentationofNhasasmanyormorezeroesthanithasones.Forexample,theinteger9,whenwritteninbinaryform,is1001.1001hastwozeroesandtwoones;thus,9isaroundnumber.Theinteger26is11010inbinary;sinceithastwozeroesandthreeones,itisnotaroundnumber.

Obviously,ittakescowsawhiletoconvertnumberstobinary,sothewinnertakesawhiletodetermine.Bessiewantstocheatandthinksshecandothatifsheknowshowmany"roundnumbers"areinagivenrange.

Helpherbywritingaprogramthattellshowmanyroundnumbersappearintheinclusiverangegivenbytheinput(1≤Start<Finish≤2,000,000,000).

Input

Line1:Twospace-separatedintegers,respectively
Startand
Finish.

Output

Line1:Asingleintegerthatisthecountofroundnumbersintheinclusiverange
Start..
Finish

SampleInput

212

SampleOutput

6


这道题还是花了不少的时间啊,本人愚笨,看了大神的代码没看懂,经过一个半小时的推敲理解,将搜索过程列出之后总算理解了他的思想

题意:算出区间内二进制中0的个数大于等于1的个数的数字有多少个

思路:数位DP确实是一个很巧妙的东西,在搜索过程中,我们要先确定首位1的放置,然后再根据这个首位去对后面所有位置的放置情况进行一次搜索即可


#include<stdio.h>
#include<string.h>
#include<algorithm>
usingnamespacestd;

intdp[50][50][50],bit[50];
//dp[k][i][j],k为长度,i,为0的个数,j为1的个数

intdfs(intpos,intnum0,intnum1,intwork,intfirst)
{
if(!pos)
{
if(first)
return1;
if(num0>=num1)
return1;
return0;
}
if(!first&&!work&&dp[pos][num0][num1]!=-1)//已经被访问过了
returndp[pos][num0][num1];
intend=work?bit[pos]:1;//判断此位能否为1
intans=0;
for(inti=0;i<=end;i++)
{
//doing&&end==i是看此位是不是算完
if(first)//first是看第一位是否放下
{
if(i==0)
ans+=dfs(pos-1,0,0,work&&end==i,1);//第一位还未放下,继续往后面看
else
ans+=dfs(pos-1,num0,num1+1,work&&end==i,0);//在这个选定的位置放下1,作为次二进制的初始
}
else
{
if(i==0)
ans+=dfs(pos-1,num0+1,num1,work&&end==i,0);//在二进制后面放0
else
ans+=dfs(pos-1,num0,num1+1,work&&end==i,0);//放1
}
}
if(!work&&!first)
dp[pos][num0][num1]=ans;//记录,防止重复访问,节省时间
returnans;
}

intsolve(intn)
{
intlen=1;
while(n)
{
bit[len++]=n&1;
n>>=1;
}
intans=dfs(len-1,0,0,1,1);
returnans;
}

intmain()
{
memset(dp,-1,sizeof(dp));
intl,r;
while(~scanf("%d%d",&l,&r))
{
printf("%d\n",solve(r)-solve(l-1));
}

return0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: