火柴游戏(match)-2022蜀山区赛初中组第3题

题目描述

锤锤和柯西在玩火柴棒游戏,他们用火柴棒拼成不同的数字。规则如下:

这是火柴所形成10个数字的方式,每个数字所需的火柴数量不一样。现在给两人每人发N根火柴棒。锤锤要用所有火柴棒摆出其所能摆出最小的数,而柯西则需要用所有火柴棒摆出其所能摆出的最大的数。当然,前导 0 或者摆出不规则的数字什么的都算是作弊。现在他们俩都想尽快知道答案,于是请你帮忙。

输入格式

从文件 match.in 中读取数据。

输入包括若干组数据。第一行为一个数字 T,表示锤锤和柯西会进行 T 次游戏。

接下来T行,每行一个正整数 N,表示火柴的数量。

输出格式

输出到文件 match.out 中。

T 行,每组数据包括一行,分别为锤锤所能摆出的最优值以及柯西所能摆出的最优值。

输入输出样例

输入样例1:

1
2

画写样例1:

1 1

说明

【数据范围】

对于 K%的数据:N<=K (K=10,20,...,100)

对于 100%的数据:2<=N<=100,0<T<100

【耗时限制】1000ms 【内存限制】256MB


这一题,上来第一想法就是dfs,但是我可以明确的告诉你们,dfs过不了一点儿

那既然dfs过不了,就得想其他方法吧,总不能不写

再仔细瞅瞅,可以发现一个求最大,一个求最小

好像可以用贪心

那既然是贪心,我们就得规划贪心策略

我们先来看最大的

        由于我们知道,两个数中,位数越大的,数值越大,那就明确了一件事情:位数要尽量的

多,也就是每一个数字占的小棍数尽量少,再回过头来看一下在0~9中哪一个最少,很明显,是1,

1只需要两根棍子;所以,我们很容易得到一个结论:

如果总棍数是一个偶数,那么就可以安排上n除以2个1,

如果是奇数呢,就安排上0~9中棍棒数次小的且为奇数的数字,也就是7,需要3根棍子,我们把他安排在第一位

string maxn(int n){
    string ans="";
    if(n%2==1) ans+='7',n-=3;
    for(int i=2;i<=n;i+=2){
        ans+='1';
    }
    return ans;
}

最大的解决了,来看一下最小的

最小的首先位数尽量小,8用的棍棒数最多,有7根,我们先安排8上

如果mod 7余0,不用判断,直接return

如果mod 7余1,把第一个8换下来,换成“10”

如果mod 7余2,不用换,直接在前面加1

如果mod 7余3,就需要再次分类讨论:

        当棍棒数为10是,别多想,直接把ans改成“22”

        否则,把前两个8改成“200”

如果mod 7余4 把第1个8换成“20”;

如果mod 7余5 不用换,直接加“2“;

如果mod 7余6,就加一个6

下面的是片段代码,完整代码在最后

string minn(int n){
    string ans="",w="00174208";
    if(n<=7){
        ans+=w[n];
        return ans;
    }
    int c=n/7,m=n%7;
    for(int i=1;i<=c;i++) ans+="8";
    if(m==0) return ans;
    if(m==1){
        ans[0]='0';
        ans="1"+ans;
    }
    else if(m==2){
        ans="1"+ans;
    }
    else if(m==4){
        ans[0]='0';
        ans="2"+ans;
    }
    else if(m==5){
        ans="2"+ans;
    }
    else if(m==3){
        if(ans.size()==1) ans="22";
        else{
            ans[0]=ans[1]='0';
            ans="2"+ans;
        }
    }
    else{
        ans="6"+ans;
    }
    return ans;
}

这个是完整代码 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <string>
using namespace std;
int T;
string maxn(int n){
    string ans="";
    if(n%2==1) ans+='7',n-=3;
    for(int i=2;i<=n;i+=2){
        ans+='1';
    }
    return ans;
}
string minn(int n){
    string ans="",w="00174208";
    if(n<=7){
        ans+=w[n];
        return ans;
    }
    int c=n/7,m=n%7;
    for(int i=1;i<=c;i++) ans+="8";
    if(m==0) return ans;
    if(m==1){
        ans[0]='0';
        ans="1"+ans;
    }
    else if(m==2){
        ans="1"+ans;
    }
    else if(m==4){
        ans[0]='0';
        ans="2"+ans;
    }
    else if(m==5){
        ans="2"+ans;
    }
    else if(m==3){
        if(ans.size()==1) ans="22";
        else{
            ans[0]=ans[1]='0';
            ans="2"+ans;
        }
    }
    else{
        ans="6"+ans;
    }
    return ans;
}
int main(){
    scanf("%d",&T);
    while(T--){
        int x;
        scanf("%d",&x);
        cout<<minn(x)<<" "<<maxn(x)<<endl;
    }
    return 0;
}
  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值