1. 程式人生 > >清北學堂模擬賽d1t2 火柴棒 (stick)

清北學堂模擬賽d1t2 火柴棒 (stick)

兩個 100% -1 con 最大的 com 數據 pre namespace

題目描述
眾所周知的是,火柴棒可以拼成各種各樣的數字。具體可以看下圖:

技術分享


通過2根火柴棒可以拼出數字“1”,通過5根火柴棒可以拼出數字“2”,以此類推。
現在LYK擁有k根火柴棒,它想將這k根火柴棒恰好用完,並且想知道能拼出的最小和最大的數分別是多少。

輸入格式(stick.in)
一個數k。

輸出格式(stick.out)
兩個數,表示最小的數和最大的數。註意這兩個數字不能有前導0。

輸入樣例
15

輸出樣例
108 7111111

數據範圍
對於30%的數據k<=10。
對於60%的數據k<=20。
對於100%的數據1<k<=100。

分析:老師說有這道圖片的題都很弱......

其實第二問非常好像,我們要讓數字最大,就一定要讓位數最大,1的火柴棒數量是最少的,我們放盡量多的1,因為k根火柴棒必須要用完,所以如果k是奇數就要放一個7,只花3根火柴棒,是最優的.

對於第一問,考慮dp,設f[i]為用i根火柴棒的最小的數,那麽f[i] = min{f[i - b[j]] +j},b[j]為數字j用的火柴棒數,開個long long就能解決了,當時我怕k=100最多有50位開不下,於是用了結構體存f數組.當然,貪心也可以做,後面若幹位用8,前面的用啥思考一下就能出來.

#include <bits/stdc++.h>

using namespace std;
const long long inf = 100000000000000000; 

struct node
{
    long long v,tot;
    int shu[210]; 
}f[210]; 

int k,a[20],b[20],sum1,sum2; void init() { for (int i = 0; i <= 9; i++) a[i] = i; b[0] = 6; b[1] = 2; b[2] = 5; b[3] = 5; b[4] = 4; b[5] = 5; b[6] = 6; b[7] = 3; b[8] = 7; b[9] = 6; } int main() { freopen("stick.in","r",stdin); freopen("stick.out
","w",stdout); init(); scanf("%d",&k); for (int i = 1; i <= k; i++) { f[i].v = inf; f[i].tot = 0; } f[0].v = 0; f[0].tot = 0; for (int i = 1; i <= k; i++) for (int j = 0; j <= 9; j++) if (i >= b[j]) { if (i == b[j] && j == 0) continue; //f[i] = min(f[i],f[i - b[j]] * 10 + a[j]); if (f[i].v > f[i - b[j]].v * 10 + a[j]) { f[i] = f[i - b[j]]; f[i].v = f[i - b[j]].v * 10 + a[j]; f[i].shu[++f[i].tot] = j; } } for (int i = 1; i <= f[k].tot; i++) printf("%d",f[k].shu[i]); printf(" "); sum1 = k % 2; sum2 = (k - sum1 * 3) / 2; for (int i = 1; i <= sum1; i++) printf("7"); for (int i = 1; i <= sum2; i++) printf("1"); printf("\n"); return 0; }

清北學堂模擬賽d1t2 火柴棒 (stick)