codeforces915c dfs

题意:一个数a和一个数b,不含前导零,移动a的数字的位置,使得a成为比b小的最大的数。

题解:用一个数组存a中的数,一个数组存b中的数。从大到小对a排序。如果a的数字个数比b少,直接输出。

如果是一样长,记录a中数字出现的次数,然后dfs。因为最大的数是1e18,直接dfs a中的数字会超时,所以就dfs 0到9这十个数

如果出现了比b中对应的数字小的数字,就直接把剩下的数字从大到小填进去,如果是一样的,就搜索下一个,如果这种情况不行

就回溯。如果成功找到了所有数字,就返回。

#pragma warning(disable:4996)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int a[20], b[20], ans[20];
int vis[20];
int La, Lb, solved;
char s1[20], s2[20];
bool cmp(int x, int y)
{
	return x > y;
}
void dfs(int x, int flag)//x代表当前是求第几个数字
{
	int i;
	if (solved)return;
	if (x == La)
	{
		solved = 1;
		return;
	}
	for (i = 9; i >= 0; i--)
	{
		if (vis[i] > 0)//数字个数大于0
		{
			if (flag || i < b[x])//之前的或者是当前的数比b对应数字小
			{
				ans[x] = i;
				vis[i]--;
				dfs(x + 1, 1);
				vis[i]++;//回溯
				if (solved)return;
			}
			else if (i == b[x])
			{
				ans[x] = i;
				vis[i]--;
				dfs(x + 1, flag);
				vis[i]++;
				if (solved)return;
			}
			/*else if (i < b[x])
			{
				ans[x] = i;
				vis[i]--;
				dfs(x + 1, 1);
				vis[i]++;
				if (solved)return;
			}*/
		}
	}
}
int main()
{
	int i, j;
	while (scanf("%s%s", s1, s2) == 2)
	{
		La = strlen(s1); Lb = strlen(s2);
		memset(vis, 0, sizeof(vis));
		for (i = 0; i < La; i++)
		{
			a[i] = s1[i] - '0';
			vis[a[i]]++;
		}
		for (i = 0; i < Lb; i++)
			b[i] = s2[i] - '0';
		sort(a, a + La, cmp);//排序
		if (La < Lb)//a的数字个数比b少
		{
			for (i = 0; i < La; i++)
				printf("%d", a[i]);
			cout << endl;
		}
		else if (La == Lb)
		{
			solved = 0;
			dfs(0, 0);
			for (i = 0; i < La; i++)
				printf("%d", ans[i]);
			cout << endl;
		}
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章