poj 2426

我去,这题废了好大功夫,其实大多过程就是广搜,可有一个过程一直不明白,就是为什么模除只有两种情况,我的理解是按照顺序,所以尽可能往后,但好像不对,希望做过这题的大神帮我指点下迷津。

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#define M 1005
int record[M];
int n,k,m;
int ans ;
/*
	a≡b(%p)
	则(a+c)%p ≡ (b+c)%p;
	则(a-c)%p ≡ (b-c)%p;
	则(a*c)%p ≡ (b*c)%p;
	所以,在这题里面,三种情况都是可以的直接用 n%k来代替了
	n % m ≡ n (mod m)

	但是有一个不行
	为什么只有两种情况,因为,有一个字典序的要求,
	还有就是,是达到那个的最短过程,那么
*/
struct node
{
	int state;
	int len;
	int pre;
	int path;
	int keep;
}q[10000];
bool isAns(int state)
{
	if((state + 1000*k)%k == ans) return true;
	return false;
}
char getcode(int a)
{
	switch(a)
	{
		case 0:return '+';
		case 1:return '-';
		case 2:return '*';
		case 3:return '%';
	}
}
void print(int index)
{
	printf("%d\n",q[index].len);
	char s[M];
	int nlen = 0;
	while(q[index].pre >= 0)
	{
		s[nlen++]=getcode(q[index].path);
		index = q[index].pre;
	}
	for(int i = nlen-1; i >= 0; i --)
	{
		printf("%c",s[i]);
	}
	printf("\n");
}
int bfs(int state)
{
	memset(q,0,sizeof(q));
	memset(record,0,sizeof(record));
	int top = 0,rail = 1;
	if(isAns(state)) return 0;
	q[top].state = (state + 1000 * k) %k;
	q[top].keep = (state + 1000 * m) %m;
	record[(q[top].state + 1000*k) %k] = 1;
	q[top].len = 0;
	q[top].pre = -1;
	while(top < rail)
	{
		int now = q[top].state;
		int nowlen = q[top].len;
		for(int i = 0; i < 4; i ++)
		{
			switch(i)
			{
				case 0:
				{
					int temp = (now + m +1000*k)%k;
					if(record[temp] == 0)
					{
						record[temp] = 1;
						q[rail].state=temp,q[rail].len=q[top].len+1,q[rail].pre=top,q[rail].path=0;
						if(isAns(temp))
						{
							print(rail);
							return q[rail].len;
						}
						rail++;
					}
					continue;
				}
				case 1:
				{
					int temp = (now - m + 1000*k)%k;
					if(record[temp] == 0)
					{
						record[temp] = 1;
						q[rail].state=temp,q[rail].len=q[top].len+1,q[rail].pre=top,q[rail].path=1;
						if(isAns(temp))
						{
							print(rail);
							return q[rail].len;
						}
						rail++;
					}
					continue;
				}
				case 2:
				{
					int temp = (now * m + 1000*k) %k;
					if(record[temp] == 0)
					{
						record[temp] = 1;
						q[rail].keep = (q[top].keep * m ) % m;
						q[rail].state=temp,q[rail].len=q[top].len+1,q[rail].pre=top,q[rail].path=2;
						if(isAns(temp))
						{
							print(rail);
							return q[rail].len;
						}
						rail++;
					}
					continue;
				}
				case 3:
				{
					if((q[top].path == 0 && q[top].len > 0) || q[top].path == 1) continue;
					int temp = (q[top].keep + 1000*k) %k;

					if(record[temp] == 0)
					{
						record[temp] = 1;
						q[rail].state=temp,q[rail].len=q[top].len+1,q[rail].pre=top,q[rail].path=3;
						if(isAns(temp))
						{
							print(rail);
							return q[rail].len;
						}
						rail++;
					}
					continue;
				}
			}
		}
		top++;
	}
	return -1;
}
int main(int argc, char const *argv[])
{
	while(scanf("%d %d %d",&n,&k,&m) != EOF)
	{
		if(n == 0 && m == 0 && k == 0)
			break;
		ans = (n+1+500*k)%k;//目标需要达到的值。
		if(bfs(n) < 0) printf("0\n");
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值