poj2426 BFS

/**
 * poj2426 BFS
 * 好像是一道AC率很低的题,非常繁琐,需要考虑的东西比较多,要认真一点做.我是看了别人的做的
 * 对于+ - *三种操作,对K取模以后的结果都不耽误最后的计算;
 * 而对于%,由于之前的性质,多次取模结果是一样的,因此%只会出现一次,那么就只有两种情况会出现
 * 第一种就是第一个操作符就是%,第二种是第一个操作符是*,%是第二个,这种情况下就产生了0
 * 而如果我们用K为模存储变量的话,一定要记得,对%操作的原数是不能先对k取模过的,否则你一定是忘了%不符合交换率
 * 知道了这些,就是注意怎么做BFS的问题了,最后再回溯一下得到路径,并不算特别复杂
 */
#include <iostream>
#include <cstring>
using namespace std;
const int MAX_NUM = 1001;

int n,k,m,big;
char op_table[5] = {'+','-','*','%',0};
char op[MAX_NUM];

struct point{
    int num;
    int father;
    char op_pre;
} p[MAX_NUM];
bool exist[MAX_NUM];

void bfs(){
    int father=0,child=1;
    int dest = (n+1+big)%k;
    p[0].num = (n+big)%k;
    p[0].op_pre = 0;
    bool finish_flag = false,repeat_flag = false;
    memset(exist,0,sizeof(exist));
    memset(op,0,sizeof(op));
    exist[p[0].num] = true;
    int tmp;

    while(father<child && !finish_flag && !repeat_flag){
        bool validflag=false;
        for(int i=0;i<4;++i){
            switch(op_table[i]){
                case '*':
                    tmp = (p[father].num*m + big)%k;
                    break;
                case '-':
                    tmp = (p[father].num-m + big)%k;
                    break;
                case '+':
                    tmp = (p[father].num+m + big)%k;
                    break;
                case '%':
                    //只有是作为第一个符号时,或者第一个符号是*且它作为第二个符号时
                    if(father == 0 || (p[father].father == 0 && p[father].op_pre == '*') ){
                        tmp = (father == 0) ? ((n%m+m)%m + big)%k : 0;//注意,father==0的情况,输入值不能是p[0].num,必须是n,因为前者已经对k取模了,而%不符合交换率;另一种情况,就直接赋值为0就可以了
                        break;
                    }
                    else{
                        validflag = true;
                    }
                default:
                    break;
            }
            if(validflag)//不符合两个条件的%操作符,就不需要考虑了
                continue;
            if(!exist[tmp]){
                exist[tmp] = true;
                p[child].num = tmp;
                p[child].father = father;
                p[child].op_pre = op_table[i];
                ++child;
            }

            if(tmp==dest){
                //output?
                finish_flag = true;
                break;
            }
        }
        ++father;
    }

    if(father == child){
        cout << 0 << endl;
    }
    else if(finish_flag){
        int x = child-1,count=0;
        while(p[x].op_pre!=0){
            op[count++] = p[x].op_pre;
            x = p[x].father;
        }
        cout << count << endl;
        for(int i=count-1;i>=0;--i){
            cout << op[i];
        }
        cout << endl;
    }

}

int main(){
    while(cin >> n >> k >> m){
        if(n==0 && k==0 && m==0){
            break;
        }
        big = k<<20;
        bfs();
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值