码迷,mamicode.com
首页 > 其他好文 > 详细

CDOJ 1260 火柴棍数字(二)

时间:2015-12-16 22:58:51      阅读:349      评论:0      收藏:0      [点我收藏+]

标签:

Fish是一条生活在海里的鱼,有一天他很无聊,于是他去捡了人类扔进海里的垃圾,打算用这些来玩些什么。

他从捡回来的垃圾堆里找到了n根火柴棍,他想把这些火柴棍拼成一个长度为m的十进制数,每个数字的拼法如下图所示。

技术分享

他想拼出来的数尽量大,这该怎么拼呢?

聪明的你,肯定知道该如何利用这n根木棒得到最大的m位数。

那就快告诉Fish吧~

当然,不能有前导0哦。

而且木棍得全部用完!

Input

第一行输入两个整数,n,m

满足 1<=n,m<=105

Output

将这m位数输出

如果不能得到任何一个m位数,请输出1

Sample input and output

Sample InputSample Output
5 2
71
1 1000
-1

 

 

 

Hint

第一个样例解释:

一开始,Fish有5个木棒,Fish用了3根木棒摆成了7的模样,用2根木棍摆成了1的模样

合在一起,组成了 71 这个数!

Fish想了想,这的确是它恰好用完5根木棍后,能够组成的最大的数。

Source

每周一题
 
分析:
贪心的思想。
什么时候可以得到m位的数呢?事实上全部使用需要木棍最少的数字1(2根)时,n取到最小,为2m,全部使用需要木棍最多的数字8(7根)时,n取到最大,为7m,
所以当n属于[2m,7m]就可以得到m位的数,而不在这个区间中时就不能得到。
if (n < 2*m || n > 7*m) printf("-1\n");

 

初始化两个数字-木棍数相对应的表格。
int t[10] = {
    6, 2, 5, 5, 4, 5, 6, 3, 7, 6
//  0  1  2  3  4  5  6  7  8  9
};
int tu[10] = {
    -1,-1, 1, 7, 4, 5, 9, 8,-1,-1
//   0  1  2  3  4  5  6  7  8  9
};

 

t[i] = j表示数字i需要j个木棍,tu[j] = i 表示j个木棍可以表示的最大单个数字为i,如果j个木棍不能表示任何单个数字,i=-1
先尽量取较大的数放前面,然后移动木棍到后面去,后面的数尽量使用木棍最少的数,也就是1(需要2个木棍)
比如说n = 19, m = 5时,
先取ans = [9, 9, 9, 0, 0], 此时剩余木棍rest = 1 < t[1] = 2
我们把第三个9变成1, 此时rest = 1 + t[9] - t[1] = 5, ans = [9, 9, 1, 0, 0]
剩余5个木棍,可以组成2个1
ans = [9, 9, 1, 1, 1], rest = 1
然后将从遍历ans, 如果加上rest数字更大,就加上。
 
最后的代码:
#include <cstdio>

int t[10] = {
    6, 2, 5, 5, 4, 5, 6, 3, 7, 6
//  0  1  2  3  4  5  6  7  8  9
};
int tu[10] = {
    -1,-1, 1, 7, 4, 5, 9, 8,-1,-1
//   0  1  2  3  4  5  6  7  8  9
};

int ans[100005];
int cur;
int rest;

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    rest = n;
    if (n < 2*m || n > 7*m) printf("-1\n");
    else {
        for (cur = 0; cur < m; cur++) {
            for (int i = 9; i >= 0; i--) {
                if (t[i] <= rest) {
                    ans[cur] = i;
                    rest -= t[i];
                    break;
                }
            }
            if (rest < 2) break;
        }
        cur -= (cur == m);
        int r = cur;
        for (int rev = m-1; rev > cur; rev--) {
            while (ans[r] == 1) r--;
            if (rest >= 2) {
                ans[rev] = 1;
                rest -= t[1];
            }
            else {
                rest += t[ans[r]] - t[1];
                ans[r--] = 1;
                rev++;
            }
        }
        for (int i = 0; i < m && rest; i++) {
            for (int j = 9; j >= 0; j--) {
                if (j > ans[i] && t[j] - t[ans[i]] <= rest) {
                    rest -= t[j] - t[ans[i]];
                    ans[i] = j;
                    break;
                }
            }
        }
        for (int k = m-1; k >= 0 && rest; ) {
            if (tu[t[ans[k]]+1] != -1) {
                ans[k] = tu[t[ans[k]]+1];
                rest--;
            }
            else {
                 k--;
            }
        }
        for (int i = 0; i < m; i++) {
            printf("%d", ans[i]);
        }
        printf("\n");
    }
    return 0;
}

 

 

CDOJ 1260 火柴棍数字(二)

标签:

原文地址:http://www.cnblogs.com/cfeitong/p/5052532.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!