预处理的广搜

Description

Petka thought of a positive integer n and reported to Chapayev the sum of its digits and the sum of its squared digits. Chapayev scratched his head and said: "Well, Petka, I won't find just your number, but I can find the smallest fitting number." Can you do the same?
 

Input

The first line contains the number of test cases t (no more than 10000). In each of the following t lines there are numbers s1 and s2 (1 ≤ s1, s2 ≤ 10000) separated by a space. They are the sum of digits and the sum of squared digits of the number n.
 

Output

For each test case, output in a separate line the smallest fitting number n, or "No solution" if there is no such number or if it contains more than 100 digits.
 

Sample Input

    
    
4 9 81 12 9 6 10 7 9
 

Sample Output

    
    
9 No solution 1122 111112
 
题意:给出s1,s2。s1为位和,s2为位的平方和。求满足该s1和s2的最小数
思路:预处理广搜。从0 0 开始搜索、每个dp[i][j]只用进队一次。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <string>
#include <string>
using namespace std;
#define maxn 108
bool dp[902][8102];
int pre[902][8102];
int ans[102];
struct Item
{
	int step,ss1,ss2;
	Item(){}
	Item(int s,int s1,int s2)
	{
		step = s;
		ss1 = s1;
		ss2 = s2;
	}
};
queue <Item> q;

void init()
{
	memset(dp,0,sizeof(dp));
	dp[0][0] = 0;
	memset(pre,-1,sizeof(pre));
	q.push(Item(0,0,0));
	while(!q.empty())
	{
		Item item = q.front();	
		q.pop();
		if(item.step >= 100)	break;
		for(int i = 1;i <= 9;i++)
		{
			int nows1 = item.ss1 + i;
			int nows2 = item.ss2 + i*i;	
			if(dp[nows1][nows2])	continue;
			if(nows1 > 900 || nows2 > 8100) break;
			dp[nows1][nows2] = 1;
			pre[nows1][nows2] = i;
			q.push(Item(item.step+1,nows1,nows2));
		}
	}
}
int main()
{
	//freopen("in.txt","r",stdin);
	init();
	int t;	scanf("%d",&t);
	while(t--)
	{
		int s1,s2;
		scanf("%d%d",&s1,&s2);
		if(s1 > 900 || s2 > 8100)	
		{
			printf("No solution\n");
			continue;
		}
		if(pre[s1][s2] == -1)	printf("No solution\n");
		else
		{
			int pos = 0;
			while(pre[s1][s2] != -1)
			{
				ans[pos++] = pre[s1][s2];
				int as = s1,bs = s2;
				s1 -= pre[as][bs];
				s2 -= pre[as][bs]*pre[as][bs];
			}
			for(int i = pos-1;i >= 0;i--)	printf("%d",ans[i]);
			printf("\n");
		}
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值