poj2426 Remainder
题意:
- 多组数据。
- 给n,m,k三个数(-1000<=n<=1000,1<k<=1000,0<m<=1000)
- 有四种操作n+m,n-m,n*m,n%m
- 求最少经过多少步将n变为(n+1)%k
思路:
求最小步数,审题后发现用BFS。枚举4种操作,特别注意n%m的操作,因为n可能为负数,所以%操作要用(n%m+m)%m。因为是多组数据,所以每次都要清空队列与flag数组(千万注意,贡献了一次Wa)。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
int n,m,k,ans;
string ans1;
bool flag[10000005];
struct ss
{
int num,sum;
string r;
};
void bfs()
{
queue<ss>q;
int sum=m*k,s;
ss res,tmp;
s=((n+1)%k+k)%k;
flag[(n%sum+sum)%sum]=1;
res.num=0; res.sum=n; res.r="";
q.push(res);
while (!q.empty())
{
res=q.front(); q.pop();
if ((res.sum%k+k)%k==s)
{
ans=res.num; ans1=res.r;
return;
}
for (int i=0; i<4; i++)
{
if (i==0) {tmp.sum=(res.sum+m)%sum; tmp.r=res.r+"+";}
else if (i==1) {tmp.sum=(res.sum-m)%sum; tmp.r=res.r+"-";}
else if (i==2) {tmp.sum=(res.sum*m)%sum; tmp.r=res.r+"*";}
else {tmp.sum=(res.sum%m+m)%m%sum; tmp.r=res.r+"%";}
tmp.sum=(tmp.sum+sum)%sum;
if (!flag[tmp.sum])
{
flag[tmp.sum]=1;
tmp.num=res.num+1; q.push(tmp);
}
}
}
}
int main()
{
while(scanf("%d%d%d",&n,&k,&m))
{
if (!n&&!m&&!k) break;
ans=0;
memset(flag,0,sizeof(flag));
bfs();
printf("%d\n",ans);
if(ans) cout<<ans1<<endl;
}
return 0;
}