2013金山西山居创意游戏程序挑战赛——初赛(2) C 卡片游戏 (hdu 4550 )

来源:互联网 发布:java旅游项目 编辑:程序博客网 时间:2024/05/16 00:38

http://acm.hdu.edu.cn/showproblem.php?pid=4550

题意:

小明最近宅在家里无聊,于是他发明了一种有趣的游戏,游戏道具是N张叠在一起的卡片,每张卡片上都有一个数字,数字的范围是0~9,游戏规则如下:
  首先取最上方的卡片放到桌子上,然后每次取最上方的卡片,放到桌子上已有卡片序列的最右边或者最左边。当N张卡片全部都放到桌子上后,桌子上的N张卡片构成了一个数。这个数不能有前导0,也就是说最左边的卡片上的数字不能是0。游戏的目标是使这个数最小。
  现在你的任务是帮小明写段程序,求出这个最小数。


思路:很明显的贪心题,首先若没有前导0的限制,则我们每次取出一个数,它和已经取出的数中最左边的数相比,若大于它,显然我们应该将它放在右边,否则我们应该将它放左边。但是现在有了前导0的限制,则按照上面的策略就会出现非法解。事实上,由于最左边的数不能是0,所以我们得到的数的位数是一定的,在这种情况下要得到最小的数,显然就是要让前边的尽量小。则我们可以按照下列策略进行取舍

我们设当前取出的数的最左边的数为tmp,初始化为0.

接下来我们一个一个从上往下卡片。

1.若我们遇到了0,则我们看需找还没取过的数中的最小值(设为mi)是否小于或等于tmp,若成立,则我们把0放到左边,并将tmp设为mi。并找到还未等于mi的数中最地下那个数的位置(设为po)。

2.若我们遇到了非0,则有两种情况

(1)如果我们当前取出的数中最左边的数不为0,则按照上面红字所示的贪心方法即可。

(2)否则,我们看当前取出的这个数是否就是1中所找到的那个数(位置为po),若是我们将它放到左边,否则放到右边。

这个方法的核心就是要保证最后得到的数左边的数尽量小。上述描述还有一些细节没有描述出来,具体实现请参考我的代码。


代码如下:

#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;char str[110];int vis[220];int main(){   //freopen("dd.txt","r",stdin);   int ncase;   scanf("%d",&ncase);   while(ncase--)   {       scanf("%s",str);       int i,len=strlen(str);       int min[110];       min[len-1]=str[len-1]=='0'?10:str[len-1]-'0';       for(i=len-2;i>=0;i--)       {           if(str[i]-'0'==0)           min[i]=min[i+1];           else if(str[i]-'0'<min[i+1])           min[i]=str[i]-'0';           else           min[i]=min[i+1];       }       int l=105,r=105;       int tmp=10,po=0,tru=0;       for(i=0;i<len;i++)       {           if(str[i]=='0')           {               if(min[i]<=tmp&&min[i]!=10)               {                   vis[l--]=0;                   tmp=min[i];                   if(!po)                   {                       po=len-1;                       while(str[po]-'0'!=min[i])                       po--;                   }               }               else               vis[++r]=0;           }           else           {               int xx=str[i]-'0';               if(!po)               {                   if(xx<=tmp)                   vis[l--]=xx,tmp=xx;                   else                   vis[++r]=xx;               }               else               {                   if(i==po)                   vis[l--]=xx;                   else                   vis[++r]=xx;               }           }       }       for(i=l+1;i<=r;i++)       printf("%d",vis[i]);       printf("\n");   }    return 0;}




原创粉丝点击