ZOJ-3596

27 篇文章 0 订阅

这题搞了我好几天。。算是做过的搜索题中对时间要求比较苛刻的了,算法稍微差点就超时。。优化了好久,开始队列里面存的是指针,状态都是新new的,这样无论怎么优化都超时。。后来参考了网上代码,把状态全放到一个大数组里面,这样每次搜的时候直接数组寻址就行了,不用再new对象,这样能险险AC,用时6s,总的来说本题就是BFS加状态压缩,状态由两个组成,一是当前余数,范围为1到1000,二是当时用过的数字,用一个二进制位表示数字是否用到,那么状态范围就是0到1<<10, 两种状态组合就是1000*1024种状态,开始就把状态用数组初始化好,然后队列里搜的时候就能直接用数组下标要记录状态了。。最后,祝自己生日快乐,happy every day!!!

#include<cstdio>
#include<deque>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<cstdlib>

using namespace std;

namespace
{
	struct Num
	{
		char c;
		pair<int, int> prev;
		bool flag;
	} N[1000][1 << 10];

	int n, m;
	deque<pair<int, int> > Q;
	vector<int> V;
	vector<char> C;

	void init()
	{
		for (int i = 0; i < 10; i++)
		{
			V.push_back(1 << i);
			C.push_back('0' + i);
		}
	}

	int digit(int bit)
	{
		int count = 0;
		while (bit)
		{
			if (bit & 1)
				count++;
			bit >>= 1;
		}
		return count;
	}

	string& remove_leading_zero(string &s)
	{
		while (s[0] == '0')
			s.erase(0, 1);
		return s;
	}

	string divide(const string &s, int n)
	{
		string t = "0";
		int rem = 0;
		for (size_t i = 0; i < s.size(); i++)
		{
			rem = rem * 10 + (s[i] - '0');
			t += (rem / n + '0');
			rem = rem % n;
		}
		return remove_leading_zero(t);
	}

	string append(pair<int, int> p)
	{
		string s;
		while (p.first || p.second)
		{
			s = N[p.first][p.second].c + s;
			p = N[p.first][p.second].prev;
		}
		return s;
	}

	void bfs()
	{
		memset(N, 0, sizeof(N));
		Q.clear();
		Q.push_back(make_pair(0, 0));
		N[0][0].flag = true;
		bool find = false;
		while (!Q.empty() && !find)
		{
			pair<int, int> p = Q.front();
			char c = N[p.first][p.second].c;
			int rem = p.first;
			int bit = p.second;
			Q.pop_front();
			for (int i = (c ? 0 : 1); i < 10; i++)
			{
				int r = (rem * 10 + i) % n;
				int b = bit | V[i];
				int dd = digit(b);
				if (!r && dd == m)
				{
					find = true;
					string ss = append(p) + C[i];
					printf("%s=%d*%s\n", ss.c_str(), n, divide(ss, n).c_str());
					break;
				}
				else if (!(N[r][b].flag) && dd <= m)
				{
					N[r][b].flag = true;
					N[r][b].prev = p;
					N[r][b].c = C[i];
					Q.push_back(make_pair(r, b));
				}
			}
		}
		if (!find)
			puts("Impossible");
	}
}

int main()
{
	init();
	int T;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d %d", &n, &m);
		bfs();
	}
	return 0;
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值