码迷,mamicode.com
首页 > 其他好文 > 详细

【bfs】hdu 1104 Remainder

时间:2015-07-25 00:17:25      阅读:257      评论:0      收藏:0      [点我收藏+]

标签:bfs

【bfs】hdu 1104 Remainder

题目链接:hdu 1104 Remainder

很不错的一道搜索题目,但是有几个关键问题要注意。

  • 最短路径,果断bfs+Queue
  • 路径的存储问题,之前只想把每一步的计算结果存储到queue(int)Q中,后来发现路径无法记录,就选择存储节点的方式并用string保存路径,queue(node)Q,开一个临时的节点node p,每进行一次运算就更新它的路径string+’op’,最终输出的一定是完整路径!!
  • 但最关键的是取模!!!!!
    discuss区有很不错的解释:as followed
    n在经过一些列的运算,可能会很大,所以溢出问题,需要考虑充分。
    因为最后比较的是两个数对k取余是否相等,因此,在队列中存储对k取余后的值,
    各种文章中谈论的都是((n op1 m)%k op2 m)%k 是不是等于(n op1 m op2 m)%k
    对于op运算+ - * 是成立的,但是%参与时,结果是不等。例如:
    记n = 2, m = 8, k =3.
    则((n * m)%k % m)%k = 1
    而(n * m % m)%k = 0。
    一言以蔽之,%不满足线性同余性,所有过程中%k的计算结果遇到%m%k就是不正确的!!!!

【key】解决办法有两个,要么就是过程中不进行任何操作,但是数据很容易溢出,及时开成long long(尝试交过WA了,6次乘法就爆了)
还有一种方法最好,每一步用%(k*m)替代%k(具体证明考察你的数学基础O(∩_∩)O),这样,既能把运算结果控制在一定范围内避免溢出,又能很好的解决%m%k的非线性同余,一举两得!~

技术分享

参考代码

/*Author:Hacker_vision*/
#include<bits/stdc++.h>
#define clr(k,v) memset(k,v,sizeof(k))
typedef long long ll;
using namespace std;

const int _max=1e6+10;
int n,m,k,res,deep,km;
bool vis[_max];
struct node{
 ll num;
 string str;
};
queue<node>Q;

void bfs(){
  node q;
  q.num=n;
  q.str="";
  Q.push(q);
  vis[(n%k+k)%k]=true;
  while(!Q.empty()){
    q=Q.front();
    Q.pop();
    if((q.num%k+k)%k==res) {
        cout<<q.str.size()<<endl;//cout<<q.num<<endl;
        cout<<q.str<<endl;
        return;
    }
    node p;p.num=q.num+1;
    for( int i = 0; i < 4; ++ i) {//遍历孩子节点
        if(i==0){
            p.num=(q.num+m)%km;
            p.str=q.str+‘+‘;
        }
        else if(i==1){
            p.num=(q.num-m)%km;
            p.str=q.str+‘-‘;
        }
        else if(i==2){
            p.num=(q.num*m)%km;
            p.str=q.str+‘*‘;
        }
        else{
            p.num=((q.num%m+m)%m)%km;
            p.str=q.str+‘%‘;
        }
        if(!vis[(p.num%k+k)%k]){ //操作有限化,访问过的节点不必入队
            Q.push(p);
            vis[(p.num%k+k)%k]=true;
        }
    }
  }
  puts("0");
}

int main(){
 // freopen("input.txt","r",stdin);
  while(cin>>n>>k>>m,(n||m||k)){
    res=((n+1)%k+k)%k;//计算机%与理论mod有出入,不管是不是负数都这样处理,省去判断了
    clr(vis,0);
    km=k*m; //%km避免数据溢出且能满足%的线性同余
    while(!Q.empty()) Q.pop(); //库函数就不能写个Q.clear()嘛!!!/(ㄒoㄒ)/~~
    bfs();
  }
  return 0;
}
  • 加粗 Ctrl + B
  • 斜体 Ctrl + I
  • 引用 Ctrl + Q
  • 插入链接 Ctrl + L
  • 插入代码 Ctrl + K
  • 插入图片 Ctrl + G
  • 提升标题 Ctrl + H
  • 有序列表 Ctrl + O
  • 无序列表 Ctrl + U
  • 横线 Ctrl + R
  • 撤销 Ctrl + Z
  • 重做 Ctrl + Y

版权声明:本文为博主原创文章,未经博主允许不得转载。

【bfs】hdu 1104 Remainder

标签:bfs

原文地址:http://blog.csdn.net/u012717411/article/details/47049149

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!