TOJ 4603 Interesting Calculator -- SPFA

2 篇文章 0 订阅

题目链接:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=4603

题目大意:给定一个数字x,令t表示一个一位数(0 - 9),可以对x进行以下三种操作:

1.在x后面添加t,即x = x * 10 + t;

2.x加上t,即x = x + t;

3.x乘以t,即x = x * t;

每一步操作有一个花费(共30种花费),求从x变到y的最小花费。

分析:很明显的搜索题目(其实我一开始有尝试贪心,但是做不出来),关键在于优化。用如下几种优化就够了:

1.x + t时t >= 1, x * t时t >= 2(效果不明显)

2.x > y明显不可能。唯一能把x变小的操作就是x * 0 = 0,把状态0加入初始状态集合,后面就不用再考虑这种情况了(重要)

3.若当前操作花费不小于现有最小值,停止操作

其实有了第2条优化就够了,剩下的是数据结构的选择,一开始我一直用优先队列,这样搜索到第一个x = y的情况就可以终止了,这在TOJ上会超时,在CSUOJ上1000+ms。后来改用普通队列,就必须搜索到队列为空。用SPFA,比优先队列快得多,在TOJ上437ms,在CSUOJ上176ms。

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
         #include 
         #include 
         
           #include 
          
            #include 
           
             #include 
            
              #include 
             
               #include 
              
                #include 
               
                 #include 
                
                  #include 
                 
                   #include 
                  
                    #define mp make_pair #define X first #define Y second #define MEMSET(a, b) memset(a, b, sizeof(a)) using namespace std; typedef unsigned int ui; typedef long long ll; typedef unsigned long long ull; typedef pair 
                   
                     pii; typedef vector 
                    
                      vi; typedef vi::iterator vi_it; typedef map 
                     
                       mii; typedef priority_queue 
                      
                        pqi; typedef priority_queue 
                       
                         , greater 
                        
                          > rpqi; typedef priority_queue 
                         
                           pqp; typedef priority_queue 
                          
                            , greater 
                           
                             > rpqp; const int MAX_N = 100000 + 2; int a[3][10]; int cost[MAX_N][2]; bool inq[MAX_N]; int main(int argc, char *argv[]) { // freopen("D:\\in.txt", "r", stdin); int x, y, i, j, cas = 0; while (cin >> x >> y) { for (i = 0; i < 3; ++i) { for (j = 0; j < 10; ++j) { scanf("%d", a[i] + j); } } MEMSET(inq, 0); MEMSET(cost, -1); pii ans(INT_MAX, INT_MAX); queue 
                            
                              q; if (x == y) { printf("Case %d: 0 0\n", ++cas); continue; } if (x < y) { q.push(x); inq[x] = true; cost[x][0] = cost[x][1] = 0; } if (x) { q.push(0); inq[0] = true; cost[0][0] = a[2][0]; cost[0][1] = 1; } while (!q.empty()) { int tmp = q.front(); q.pop(); inq[tmp] = false; if (tmp == y) { ans = min(ans, mp(cost[tmp][0], cost[tmp][1])); continue; } if (cost[tmp][0] > ans.X || cost[tmp][0] == ans.X && cost[tmp][1] >= ans.Y) continue; int nx, nc, ns = cost[tmp][1] + 1; for (i = 0; i < 3; ++i) { for (j = i; j < 10; ++j) { if (i == 0) nx = tmp * 10 + j; else if (i == 1) nx = tmp + j; else nx = tmp * j; if (nx > y) break; nc = cost[tmp][0] + a[i][j]; if (nc < cost[nx][0] || nc == cost[nx][0] && ns < cost[nx][1] || cost[nx][0] == -1) { cost[nx][0] = nc; cost[nx][1] = ns; if (!inq[nx]) { q.push(nx); inq[nx] = true; } } } } } printf("Case %d: %d %d\n", ++cas, ans.X, ans.Y); } return 0; } 
                             
                            
                           
                          
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
       
      
      
     
     
    
    
   
   


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值