poj 2426

题目大意:给出三个数n,k,m,n可以+m、-m、*m、%m,每次求出的结果,再用n保存起来,%的定义如下:

若n=x*m+q 满足m>1 && q>=0 则q为n%m的值(和平常取余不一样)。

求最少多少步使得n的初始(n+1)%k等于当前的 n%k,并输出操作符顺序,若有多种解则输出操作符序列最小的,最小的定义就不说了。

WA了n次不知道为何,后来看了大牛的分析才得知%的出现是可以推算出来的。

若不加访问标志的话,复杂度必然会高,若果我们将每次取得的n值,做下n=n%k的话那么我们就可以定义一个访问标志数组。

那么这么做对不对呢?我们先看一下 ((n ope m)%k ope m) %k 是不是等于(n ope m ope m)%k ,显然+、-、*都是可以的。

若ope={+,-,*};

((n ope m)%k ope m )%k

=( (n ope m)%k%k ope (m%k)) %k

= ((n poe m)%k ope (m%k))%k

= (n ope m ope m)%k;

所以对于+、-、* 我们可以按照上述思路做的。

我们再看一下ope 取‘%’的情况:

其实我们只看(n  ope  m)%k %m 是不是等于 (n  ope  m)%m 就行了,显然是不等的。其实我们可以肯定 n经过一系列对m的操作(+,-,%)最终对m取余的结果一定是n%m,但对于‘*’显然 n*m%m==0;

总而言之:只要我们知道n%m和0是不是结果后,我们就没必要按‘%’扩展节点了,所以如果‘%’出现,要么出现在第一步,要么出现在第二步(前面必为‘*’);

#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;
struct node
{
int cur;
char sign;
int father;
};
node Q[100000];
int visit[1001];
char path[1000];
int GetPath(int tail,char * p)
{
int count=0;
stack <char> S;
int i,head=0;
for(i=tail;i>head;i=Q[i].father)
{
count++;
S.push(Q[i].sign);
}
i=0;
while(!S.empty())
{
p[i++]=S.top();
S.pop();
}
p[i]='\0';
return count;
}
int bfs(int n,int m,int k,int result)
{
int head,tail,w;
head=tail=0;
node e={n,' ',0};
Q[tail++]=e;
while(head<tail)
{
e=Q[head++];
if(e.cur==result)
{
return GetPath(head-1,path);
}
w=(e.cur+m)%k;
if(w<0) w+=k;
if(!visit[w])
{
node ee={w,'+',head-1};
Q[tail++]=ee;
visit[w]=1;
}
w=(e.cur-m)%k;
if(w<0) w+=k;
if(!visit[w])
{
node ee={w,'-',head-1};
Q[tail++]=ee;
visit[w]=1;
}
w=(e.cur*m)%k;
if(w<0) w+=k;
if(!visit[w])
{
node ee={w,'*',head-1};
Q[tail++]=ee;
visit[w]=1;
}
//重点是以下三行
if(e.sign=='*') w=0;
else if(tail!=4) continue;
if(tail==4) w=(e.cur%m+m)%m;

if(!visit[w])
{
node ee={w,'%',head-1};
Q[tail++]=ee;
visit[w]=1;
}
}
return 0;
}
int main()
{
int n,m,k,res,inValue;
while(scanf("%d%d%d",&n,&k,&m))
{
if(n==0 && m==0 && k==0) break;
memset(visit,0,sizeof(visit));
inValue=((n+1)%k+k)%k;
res=bfs(n,m,k,inValue);
if(res==0)
printf("0\n");
else
printf("%d\n%s\n",res,path);
}
return 0;
}



posted @ 2012-03-01 08:55  书山有路,学海无涯  阅读(458)  评论(0编辑  收藏  举报