世界杯现在才结束 2006-08-07

 

The 2006 FIFA World Cup Final was held in Berlin, Germany on July 9th, 2006, with France against Italy. Both France and Italy are the conquerors of the European soccer field. Soccer fans from all over the world came to Berlin Olympic Stadium to celebrate this world's biggest soccer party. In front of the ticket booth outside the stadium, we observed something interesting:

The ticket for the final match costs $50. There are m fans in the line having only $50 bill and n fans having only $100 bill. The ticket booth does not hold any changes. Please calculate in how many ways can these (m+n) soccer fans all get their tickets without the ticket booth running out of changes.

Input

Every pair of data consists of two non-negative integers m, n(not exceed 300), separated by a space. The last line of the input is a line containing two zeros.

Output

For every pair of data, output the number of ways the fans could line up.

Sample Input

 

Sample Output

 

Hint

We assume no difference between fans other than the type of bills they hold. For example, in Sample 3, there is only one way for three people to line up if all of them have $50 bill.

这是我看的第一道"那里"的题目,乍看之下觉得很难,同时还看了另一道.但一下机器就很有感觉,开始思考起来.转天马上就写了一个递归的程序.

但事情没这么简单,这毕竟是一道AC率不到30%的题目.我发现递归程序不用说300,到了15,15就出不来数了.

然后又用回溯写,希望能和棋盘一样快一点,可是结果更糟,还有错.

不知道是幸运还是不幸,转天就学了动态规划法,又是一阵的很有感觉,但问题是按我写递归的思路,要把问题划分成S,M,N.S为当时柜台拥有50美圆数.那样如果象书上所写要用300X300X300的空间,连申请都成问题.我又思考了很多别的方法,还是一样不理想.

隔了很多之后,前天,我在某论坛发一帖询问动态规划中空间的问题,被一网友"乌鸦丘比特"问我要这看这题目.于是发到网上,不久就被解决了。

d[m][n]保存

d[m][n]=
        0                                   :m<n
        d[m][n-1]                     :m=n
        d[m][n-1]+d[m-1][n]   :m>n
        1                                   :n=0

说实话看了这么多天动态规划的例题了,这个答案让我很懊恼,本身再简单不过的了,思路很清楚,为什么我就局限于S,M,N而忽略了M,N了呢?可惜开始看这题目时间早了点,如果刚学动态规划,我想会好点吧,郁闷到家了.

即使这样,我还是感到心情很放松,一块石头落地了.也更有了继续学的欲望.

但更使我高兴的的是,问题就此解决不了,还有更美妙的东西.

 因为申请300X300的空间并不小,而根据后面的验证,每个空间不再是平时的int而必须使用最大的long double !

所以即使使用动态规划也仍然离不开一开始要解决的问题,节省空间.乌鸦告诉我要用滚动数组.

不再多说,结合这道题阐述:

                               (m-1,n)     (m-1,n+1)

           (m,n-1)       (m,n)        (m,n+1)

任何一个m,n都是由位于自己上面和左面的单元而结合得到的,如此只要保留两行(如果你是以n为外循环竖着的话就保留两列)即可,这样算只针对一对m,n不会解决所有.如此循环,用后面覆盖前面的,达到节省空间的目的.

也是道理很简单,为什么我就没想出来,哎,什么时候能不SB一次啊?

#include <stdio.h>


long double WorldCup(int m,int n){
 long double roll[2][301];
 for(int i=0;i<=n;i++) roll[0][i]=0;
 for(int j=1;j<=m;j++){
  for(i=0;i<=n;i++){
   if(i==0) roll[j%2][i]=1;
   else if(i>j) roll[j%2][i]=0;
   else if(i==j) roll[j%2][i]=roll[j%2][i-1];
   else{
    roll[j%2][i]=roll[(j-1)%2][i]+roll[j%2][i-1];
   }
  }
 }
 return roll[m%2][n];
}

int main(){
 printf("%.0f/n",WorldCup(300,300));
 return 0;
}

简单易读,可以说是我想象中的完美了,但可惜不是我想出来的...还是要感谢"乌鸦丘比特",虽然他看不到.

我试了很多类型,最后发现似乎不用long double 基本都不行,最后出来的数大的吓人,但速度一点也没有影响.

我什么时候才能达到人家的水平呢?也许象以前一样,只要半年或者一年,但我即没那些时间,而且到那时候恐怕已经意义不大了......

世界杯到现在才结束,我的路还长着呢.

1
0
1

1 1
1 2
3 0
0 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值