TOJ--3071:Number Game (BFS)

1. 题目源地址:http://acm.tju.edu.cn/toj/showp.php?pid=3071

2. 题目大意:给出K和P两个数,对K进行乘2或者除2(当K为偶数时),或者加1操作。输出使K变成P的最少操作步数。

3. 源代码:

         以下给出两种代码,一种使用队列,另外一种使用数组实现队列。两种代码本质上是相同的,只不过用了不同的方式实现队列功能。

         本题和POJ上的3278:Catch The Cow很相似,给出该题的解题报告链接:http://blog.csdn.net/u012856866/article/details/38872643

(1)使用队列

#include<iostream>
#include<queue>
#include<memory.h>
#define MAX 100010
using namespace std;

int visited[MAX];
int K,P,ans;

struct node
{
   int x;
   int step;
}start,current,next;

int BFS()
{
    queue<node> Q;
    int i;
    
    start.x=K;
    start.step=0;
    Q.push(start);
    visited[start.x]=1;
    
    while(!Q.empty())
    {
       current=Q.front();
       Q.pop();
       
       for(i=0;i<3;i++)
       {
          if(i==0)   next.x=current.x*2;
          
          else if(i==1)
          {
             if(current.x%2==0)
                next.x=current.x/2;
          } 
          
          else if(i==2)   next.x=current.x+1;
          
          next.step=current.step+1;
          if(next.x==P)   return next.step;
          
          if(next.x>0 && next.x<100000 && !visited[next.x])
          {
             Q.push(next);
             visited[next.x]=1;
          }
       }
    }
    return 0;
}


int main()
{
    int caseNum;
    cin>>caseNum;
    while(caseNum--)
    {
       memset(visited,0,sizeof(visited));
       cin>>K>>P;
       ans=BFS();
       if(ans)   cout<<ans<<endl;
       else      cout<<-1<<endl;
    }
    return 0;
}

(2)使用数组实现队列功能

//TJU Exam 2008--3071:Number Game     
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define max 100000
using namespace std;

int visited[max];

struct Point
{
    int x;
    int step;
}queue[max];

int BFS(int s, int e)
{
   int i,j,top,tx;
   queue[0].x=s;
   queue[0].step = 0;
   visited[s] = 1;
   top = 1;
   for(i=0;i<top;i++)
   {
      if(queue[i].x == e)// 当得到满足条件的数时,返回 step 
         return queue[i].step;
         
       tx = queue[i].x*2;  // 1. Multiply current number by 2
       
       if(tx<max && !visited[tx])
       {
         queue[top].x = tx;
         queue[top].step = queue[i].step+1;
         visited[tx] = 1;
         top++; 
       }
       
       if(queue[i].x%2 ==0)  // 2. Divide current number by 2, if current number is even.
       {
         tx = queue[i].x/2;
         if(tx>0 && !visited[tx])
         {
            queue[top].x = tx;
            queue[top].step = queue[i].step +1;
            visited[tx] = 1;
            top++;
         }
       }
       
       tx = queue[i].x +1;  // 3. Increase current number by 1
       
       if(tx<max &&!visited[tx])
       {
          queue[top].x = tx;
          queue[top].step = queue[i].step +1;
          visited[tx]=1;
          top++;
       }   
   }
   return -1;   
}

int main()
{
    int start,end,cas;
    cin>>cas;
    while(cas--)
    {
       cin>>start>>end;
       memset(visited,0,sizeof(visited));
       cout<<BFS(start,end)<<endl;
    }
    return 0;
}

(数组实现队列简化版):

#include<iostream>
#include<memory.h>
using namespace std;

int visited[100010];

struct node
{
   int x;
   int step;
}queue[100010];

int BFS()
{
    int i,j,top,tx;
    queue[0].x=K;
    queue[0].step=0;
    visited[queue[0].x]=1;
    
    top=1;
    for(i=0;i<top;i++)
    {
       if(queue[i].x==P)
          return queue[i].step;
       
        for(j=0;j<3;j++)  
        {  
          if(j==0)  tx=queue[i].x*2;  //乘2 
          else if(j==1)  //除2 
          {  
             if(queue[i].x%2==0)  
                tx=queue[i].x/2;  
          }  
          else if(j==2)   tx=queue[i].x+1; //加1 
          
          //将tx如队列        
          if(tx>0 && tx<100000 && !visited[tx])  
          {  
             queue[top].x=tx;
             queue[top].step=queue[i].step+1;
             visited[tx]=1;
             top++; 
          }  
        }  
    }
    return 0;
}

int main()  
{  
    int caseNum;  
    cin>>caseNum;  
    while(caseNum--)  
    {  
       memset(visited,0,sizeof(visited));  
       cin>>K>>P;  
       ans=BFS();  
       if(ans)   cout<<ans<<endl;  
       else      cout<<-1<<endl;  
    }  
    return 0;  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值