Interesting Calculator (最短路,广搜+优先队列,dp)(简单题)

There is an interesting calculator. It has 3 rows of buttons.

 

Row 1: button 0, 1, 2, 3, ..., 9. Pressing each button appends that digit to the end of the display.

Row 2: button +0, +1, +2, +3, ..., +9. Pressing each button adds that digit to the display.

Row 3: button *0, *1, *2, *3, ..., *9. Pressing each button multiplies that digit to the display.

 

Note that it never displays leading zeros, so if the current display is 0, pressing 5 makes it 5 instead of 05. If the current display is 12, you can press button 3, +5, *2 to get 256. Similarly, to change the display from 0 to 1, you can press 1 or +1 (but not both!).

 

Each button has a positive cost, your task is to change the display from x to y with minimum cost. If there are multiple ways to do so, the number of presses should be minimized.

Input

There will be at most 30 test cases. The first line of each test case contains two integers x and y(0<=x<=y<=105). Each of the 3 lines contains 10 positive integers (not greater than 105), i.e. the costs of each button.

Output

For each test case, print the minimal cost and the number of presses.

Sample Input
12 2561 1 1 1 1 1 1 1 1 11 1 1 1 1 1 1 1 1 11 1 1 1 1 1 1 1 1 112 256100 100 100 1 100 100 100 100 100 100100 100 100 100 100 1 100 100 100 100100 100 10 100 100 100 100 100 100 100
Sample Output
Case 1: 2 2Case 2: 12 3
思路:
1.dp的思想,当前状态为最优,最初状态是val[n]=0;
2.广搜的思想,通过优先队列双for更新val[x]最小值(剪枝)。
3.而这道题该可以被看做是最短路,用spfa进行。基本思路是,1-100000都被当作一个点,
从当前点到下一个点,通过某种或者是某几种运算,记录步数,和相应的花费,
更新节点,得到最小值。
我的失误是,用map容器写成了更新最小值的那个数组,结果是以nlogn的时间复杂度进行访问。
还有其他细节,值得思考。


小启发:原来不止以前的模板题可以用最短路。让我真正理解了。感谢这道题。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<map>
#include<stack>
#include<queue>
#include<vector>
using namespace std;
typedef long long LL;
const int maxn=100050;
const int INF=0x3f3f3f3f;
int cost[3][10];
int dis[maxn],num[maxn];
int vis[maxn];
int st,ed;
int Case=1;
void spfa()
{
    memset(dis,INF,sizeof(dis));
    memset(vis,0,sizeof(vis));
    queue<int>q;
    int u,v,t;
    q.push(st);
    num[st]=dis[st]=0;
    while(!q.empty())
    {
        u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=0; i<3; i++)
            for(int j=0; j<10; j++)
            {
                if(i==0)
                    v=u*10+j;
                else if(i==1)
                    v=u+j;
                else
                    v=u*j;
                if(v>ed)
                    break;
                if(dis[v]<=dis[u]+cost[i][j])
                    continue;
                dis[v]=dis[u]+cost[i][j];
                num[v]=num[u]+1;
                if(!vis[v])
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
    }
    printf("Case %d: %d %d\n",Case++,dis[ed],num[ed]);
}
int main()
{
    while(~scanf("%d%d",&st,&ed))
    {
        for(int i=0; i<3; i++)
            for(int j=0; j<10; j++)
                scanf("%d",&cost[i][j]);
        spfa();
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值