Google 10月份在线笔试ProblemC(个人代码,未必最优,请不吝赐教)

Problem

Alice is a smart student who is very good at math. She is attending a math class. In this class, the teacher is teaching the students how to use a calculator. The teacher will tell an integer to all of the students, and the students must type that exact number into their calculators. If someone fails to type the number, he or she will be punished for failing such an easy task!

Unfortunately, at the beginning of the class, Alice finds that her calculator is broken! She finds that some of the number buttons are totally broken, and only the "multiply" and "equals" operator buttons are available to use. So she can only use these buttons to get the number quickly.

For instance, the teacher may say the number "60", while Alice's calculator can only type "1", "2" and "5". She could push the following buttons:

  • Button "15" (2 clicks)
  • Button "multiply" (1 click)
  • Button "2" (1 click)
  • Button "multiply" (1 click)
  • Button "2" (1 click)
  • Button "equals" (1 click)
This method requires 7 button clicks. However, if Alice uses "12*5=", only 5 clicks are needed. Of course Alice wants to get the integer as fast as possbile, so she wants to minimize the number of button clicks. Your task is to help her find a way to get the required number quickly.

Input

The first line of the input gives a number T, the number of integers the teacher says. T test cases follow.

Each case contains two lines. The first line contains ten numbers each of which is only 0 or 1. the ith number (starting from 0) is "1" if the number i can be clicked, or "0" if it is broken. The second line contains only one number X, the integer the teacher tells everyone.

Output

For each test case, output one line containing "Case #x: y", where x is the test case number (starting from 1) and y is the minimum number of button clicks needed, or "Impossible" if it is not possible to produce the number.

Limits

1 ≤ T ≤ 100.

Small dataset

1 ≤ X ≤ 100.

Large dataset

1 ≤ X ≤ 106.

Sample


Input 
 

Output 
 
3
0 1 1 0 0 1 0 0 0 0
60
1 1 1 1 1 1 1 1 1 1
128
0 1 0 1 0 1 0 1 0 1
128

Case #1: 5
Case #2: 4
Case #3: Impossible

The first sample case is explained in problem statement.

In the second case, all digits are available, so Alice can just press "1", "2", "8" and then "equals" to get the result. Please note that she still needs to press "equals" in the last step, even though there are no calculations.

For the last case, it's impossible since Alice cannot input any even numbers.


解法:

这道题刚看到的时候完全没有头绪,想着总不能挨个数去遍历吧,一直没想到什么好的解法,后来看了下别人代码,秒懂了,用dp可解,我们可以首先找出从0到要求的X中间有哪些数是可以按出来的,需要多少步才能按出来,然后再求这些可按出来的数的倍数是否能按出来,需要多少步才能按出来,因为X如果能按出来,那么其必定是某个数的倍数,所以这样必定能得出结果来。

(这道题搞错了大集合和小集合的数据,查了很久才查出来,好蛋疼,只能说编程的时候一定要注意各种细节。)


具体代码如下,大小集合通用:


#include <iostream>
#include <fstream>
using namespace std;

#define BTNMAX  10
#define VALMAX  1000010

#define MAXNUM  1000000000

int valid[BTNMAX];
int dp[VALMAX];

int clickNum(int wantNum)
{
<p class="p1"><span class="s1">    </span><span class="s2">int</span><span class="s1"> times = </span><span class="s3">0</span><span class="s1">;</span></p><p class="p1"><span class="s1">    </span><span class="s2">if</span><span class="s1"> (wantNum == </span><span class="s3">0</span><span class="s1">)</span></p><p class="p1"><span class="s1">    {</span></p><p class="p1"><span class="s1">        </span><span class="s2">return</span><span class="s1"> </span><span class="s4">valid</span><span class="s1">[</span><span class="s3">0</span><span class="s1">] > </span><span class="s3">0</span><span class="s1"> ? </span><span class="s4">valid</span><span class="s1">[</span><span class="s3">0</span><span class="s1">] : -</span><span class="s3">1</span><span class="s1">;</span></p><p class="p1"><span class="s1">    }</span></p><p class="p1"><span class="s1">    </span><span class="s2">int</span><span class="s1"> want = wantNum;</span></p><p class="p1"><span class="s1">    </span><span class="s2">while</span><span class="s1"> (want > </span><span class="s3">0</span><span class="s1">)</span></p><p class="p1"><span class="s1">    {</span></p><p class="p1"><span class="s1">        </span><span class="s2">int</span><span class="s1"> remain = want % </span><span class="s3">10</span><span class="s1">;</span></p><p class="p1"><span class="s1">        </span><span class="s2">if</span><span class="s1"> (</span><span class="s4">valid</span><span class="s1">[remain] == </span><span class="s3">0</span><span class="s1">)</span></p><p class="p1"><span class="s1">        {</span></p><p class="p1"><span class="s1">            </span><span class="s2">return</span><span class="s1"> -</span><span class="s3">1</span><span class="s1">;</span></p><p class="p1"><span class="s1">        }</span></p><p class="p1"><span class="s1">        times++;</span></p><p class="p1"><span class="s1">        want = want / </span><span class="s3">10</span><span class="s1">;</span></p><p class="p1"><span class="s1">    }</span></p><p class="p1"><span class="s1">    </span><span class="s2">return</span><span class="s1"> times;</span></p>}

int minClicks(int wantNum)
{
    // 此处应该从0开始,不然如果问0或者1最少要多少次的时候就会出错。
    for (int i = 0; i <= wantNum; i++)
    {
        int times = clickNum(i);
        if (times > 0)
        {
            dp[i] = times;
        }else
        {
            dp[i] = MAXNUM;
        }
    }
    // generate dp
    for (int i = 2; i * i <= wantNum; i++)
    {
        if (wantNum % i != 0)
        {
            continue;
        }
        int k = i;
        int times = clickNum(k);
        if (times > 0)
        {
            for (int j = 2 * k; j <= wantNum; j += k)
            {
                dp[j] = min(dp[j], dp[j / k] + times + 1);
            }
        }
        k = wantNum / i;
        times = clickNum(k);
        if (times > 0)
        {
            for (int j = 2 * k; j <= wantNum; j += k)
            {
                dp[j] = min(dp[j], dp[j / k] + times + 1);
            }
        }
    }
    if (dp[wantNum] > 0 && dp[wantNum] < MAXNUM)
    {
        return dp[wantNum] + 1;
    }else
    {
        return -1;
    }
}

int main(int argc, const char * argv[])
{
    // insert code here...
    int T, idx = 0;
    cin >> T;
    while (idx < T)
    {
        idx++;
        for (int i = 0; i < BTNMAX; i++)
        {
            cin >> valid[i];
        }
        int wantNum;
        cin >> wantNum;
        cout << "Case #" << idx << ": ";
        int times = minClicks(wantNum);
        if (times > 0)
        {
            cout << times << endl;
        }else
        {
            cout << "Impossible" << endl;
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值