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;
}

 

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