国色天香(match.pas/c/cpp)
庭前芍药妖无格,池上芙蕖净少情。唯有牡丹真国色,花开时节动京城。
——唐· 刘禹锡《赏牡丹》
芍药花再红终究妖艳无格。终不及牡丹,国色天香。
——乌拉那拉氏宜修
华妃总是想要用自己的气焰打压皇后,正好有一天,皇上有兴趣来玩一个火柴游戏,让华妃和皇后都来参与。规则如下:这是火柴所形成 9 个数字的方式,每个数字所需的火柴数量不一样。现在皇上给每个人发了 N 根火柴,华妃要摆出其所能摆出最小的数,而皇后则需要摆出其所能摆出的最大的数。当然,皇上是不容糊弄的,前导 0 或者摆出不规则的数字什么的都算是作弊。获胜者的奖励则是皇上今晚会翻她的牌子。现在皇后与华妃都使出浑身解数,而在一旁观看的甄嬛则想尽快知道答案。
是了,老师出的题比较奇葩……
这道题我个人觉得是贪心。
且听王三岁解释一下:
1.每一个数字的所用火柴棒数量是固定的,也就是我们可以分为10种情况——虽然10种情况并不多,可是有很多个人感觉用不到
2.最大最大最小值有一定的特殊性,我感觉是有规律的
3.最重要的是……用DP和图论感觉大材小用了,而枚举就是10^10,超了而且写着烦 (´Д` )
那么我们来探索一下最大最小值的特殊性:
最大值:
1)很容易想到要用最少的火柴来拼最大的数字
2)从常识的角度来看,位数越多拼出的数字就越大
3)从数学的角度来讲,越大的数字放在越高的位上数字整体就会更大
分析完以后
我们可以这么写
首先找到火柴的总数n
因为最少需要两个火柴能拼出一位数1
所以先除二
附代码:
int a[10001]={0};
int max(int n)
{
int c,lenth=0;
lenth=n/2;
for(int i=1;i<=lenth;i++)
{
a[i]=1;
}
c=n%2;
if(c==1)
{
a[1]=7;
}
return lenth;
}
好了以上是求最大值。
接下来是最小值:
1)首先是位数最少;
2)每一位尽可能多的消耗火柴;
3)小的尽量排前面;
每一位能消耗的最大值就是7根火柴,召唤出一个8(莫名中二病犯了)
然后我们同样取余数c
这个时候就有趣了:
如果余数为3:
1)如果剩一个八:从8拿两个火柴可以组成22而不是78
2)如果剩两个八:从两个8拿两根火柴可以组成200
如果余数为4:
1)如果有一个八:取一个变成20而不是48
如果余数为6:
1)如果为第一位:取6而不是0
如果余数为1:
1)如果有一个八:取一个变成10
附上召唤王三岁的代码:(为方便可读性没有简化代码)
int b[1001]={0};
int min(int n)
{
int c,lenth=0;
lenth=n/7;
for(int i=1;i<=lenth;i++)
{
b[i]=8;
}
c=n%7;
if(c==0)
{
return lenth;
}
if(c==3)
{
if(lenth>=2)
{
b[lenth]=0;
b[lenth-1]=0;
lenth++;
b[lenth]=2;
return lenth;
}
if(lenth==1)
{
b[lenth]=2;
lenth++;
b[lenth]=2;
return lenth;
}
if(lenth==0)
{
lenth++;
b[lenth]=7;
return lenth;
}
}
if(c==4)
{
if(lenth>=1)
{
b[lenth]=0;
lenth++;
b[lenth]=2;
return lenth;
}
lenth++;
b[lenth]=4;
return lenth;
}
if(c==6)
{
lenth++;
b[lenth]=6;
return lenth;
}
if(c==1)
{
if(lenth>=1)
{
b[lenth]=0;
lenth++;
b[lenth]=1;
return lenth;
}
}
else
{
lenth++;
if(c==2)
{
b[lenth]=1;
}
if(c==5)
{
b[lenth]=2;
}
return lenth;
}
}
好了这是最符合刚刚思考过程的代码。
当然还有简化版只有35行(然而因为思路会有所改动所以没给出)
lenth被返回后倒序输出b数组即可