现在的位置: 首页 > 综合 > 正文

HDU 1104题Remainder(bfs)

2019年02月26日 ⁄ 综合 ⁄ 共 2045字 ⁄ 字号 评论关闭

题目链接~~>

         开始做这一题时很快便写出来了,但是找不到结束条件,用一个数组标记但是数有可能很大,这样会标记不了,于是乎百度了一下,要%k * m,这样会将很大的数缩小到k * m的范围内,这样就可以标记了,但是还是不明白为什么%k * m,为什么不 % k。下面是某个大牛的解释:             

         题意:(注意题目中的%是指mod)开始给了你n, k, m。。。。每次由+m, -m, *m, modm得到新的N,继续对N这样的操作,直到(n+1) mod k== N mod k时结束。。。并且打印路径。

        %与mod的区别:%出来的数有正有负,符号取决于左操作数。。。而mod只能是正(因为a = b * q + r (q > 0 and 0 <= r < q), then we have a mod q = r    中r要大于等于0小于q)。。。。。所以要用%来计算mod的话就要用这样的公式:a mod b = (a % b + b) % b ,括号里的目的是把左操作数转成正数。由于新的N可以很大,所以我们每一步都要取%,而且最后要mod
k,正常来说每步都%k就行了,但是由于其中的一个操作是N%m,所以我们每一步就不能%k了(%k%m混用会导致%出来的答案错误),而要%(k *m)(其实%(k,m的公倍数都行))然后,vis[这里放的要是遍历的点mod k (想清楚标记的目的是避免结果重复)]

而那四个操作避免过大则取余就可以了,而不需要取mod。

代码:

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
using namespace std ;
int n,m,k,c,mx,r1,r2,km;
int vis[2222222],p[10000],father[10000];
struct zhang
{
    int x,y,bu;
};
int bfs(int x)
{
    queue<zhang>q;
    zhang current,next;
    int i=0;
    memset(vis,0,sizeof(vis));
    current.x=x;
    current.y=0;
    current.bu=0;
    q.push(current);
    father[0]=0;
    while(!q.empty())
       {
           current=q.front();
           q.pop();
           if(vis[(current.x%km+km)%km])
                 continue;
           next.x=((current.x+m)%km+km)%km;
           next.y=++i;
           next.bu=current.bu+1;
           father[next.y]=current.y;
           p[next.y]=1;
           if(next.x%k==c)
             {
                 mx=next.bu;
                 return next.y;
             }
           else
                    q.push(next);
             next.x=((current.x-m)%km+km)%km;
             next.y=++i;
             next.bu=current.bu+1;
             father[next.y]=current.y;
             p[next.y]=2;
             if(next.x%k==c)
             {
                       mx=next.bu;
                 return next.y;
             }
           else
                     q.push(next);
             next.x=((current.x*m)%km+km)%km;
             next.y=++i;
             next.bu=current.bu+1;
             father[next.y]=current.y;
             p[next.y]=3;
             if(next.x%k==c)
             {
                        mx=next.bu;
                 return next.y;
             }
           else
                      q.push(next);
               next.x=((current.x%m+m)%m)%km;
               next.y=++i;
               next.bu=current.bu+1;
               father[next.y]=current.y;
               p[next.y]=4;
             if(next.x%k==c)
             {
                        mx=next.bu;
                 return next.y;
             }
           else
                    q.push(next);
            vis[(current.x%km+km)%km]=1;//标记
       }
    return -1;
}
void find(int x)//递归打印路径
{
    if(father[x]!=x)
      {
            find(father[x]);
           if(p[x]==1)
                   printf("+");
           else if(p[x]==2)
                   printf("-");
           else if(p[x]==3)
                   printf("*");
           else if(p[x]==4)
                   printf("%%");
      }
}
int main()
{
    int q;
   while(scanf("%d%d%d",&n,&k,&m)!=EOF)
   {
         if(n==0&&k==0&&m==0)
                   break;
         km=k*m;
         c=((n+1)%k+k)%k;//题目中说r为正
         q=bfs(n);
      if(q!=-1)
          {
              printf("%d\n",mx);
              find(q);
          }
      else printf("0");
              printf("\n");
   }
    return 0;
}

 

      

抱歉!评论已关闭.