CodeForces 1384C. String Transformation 1(贪心)

题意:一个人有两个字符串A和B,两个字符串具有相同的长度n\((|A| = |B| = n)\),包含前20个小写字符('a'到't')。每一次操作,这个人可以选择A字符串中字符相同的字母,然后从中选择一些位置,并把这些位置的字母变大。求字符串A变到字符串B的最少操作次数。

分析:我们可以贪心地进行操作,对于"aab"--->"bbc",我们可以先把"aa"变成"bb",那么"aab"--->"bbb",然后把第三个字母'b'变成'c',那么'aab'--->'bbc'。我们可以通过从小到大枚举每个字母,检测字符串A和给定字母是否相同,然后求取对应位置的字母和这个字母相隔的差,在这些差中取最小值,意思是指对于"aabc"--->"bdec",如果枚举到了'a'字母,我们可以得到第一个字符串的第一个字母'a'和第二个字符串的第一个字母'b'的差1,第一个字符串的第二个字母'a'和第二个字符串的的第二个字母'd'之间的差3,对这个差取最小值,是我们每次要变化的值,对于所有的a,加上这个1,那么'bbbc'->'bdec'。我们可以通过这个贪心策略,得到最优解。每次枚举的一个字母,都可以把A字符串相同的字母消除掉。所以最多不超过20次。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <algorithm>

using namespace std;
const int N = 100005;
const int inf = 0x3f3f3f3f;
char a[N], b[N];
int len;
int modify(int c)
{
	int mn = inf;
	for (int i = 1; i <= len; ++i)
	{
		if (a[i] == b[i]) continue;
		if (a[i] - 'a' == c)
		{
			if (a[i] > b[i]) return -1;
			mn = min(mn, b[i] - a[i]);
		}
	}
	for (int i = 1; i <= len; ++i)
	{
		if (a[i] - 'a' == c)
		{
			if (a[i] < b[i])
			{
				a[i] += mn;
			}
		}
	}
	//bool flag = true;
	if (mn == inf) return 0;
	return 1;
}
int main() 
{	
	int t;
	scanf("%d", &t);

	while (t--)
	{
		int n;
		scanf("%d", &n);

		scanf("%s%s", a + 1, b + 1);

		len = strlen(a + 1);

		bool flag = false;
		int res = 0;
		//枚举20个字符
		for (int i = 0; i < 20; ++i)
		{
			int g = modify(i);
			if (g == -1)
			{
				flag = true;
				break;
			}
			res += g;
		}
		if (!flag)
		{
			printf("%d\n", res);
		}
		else
		{
			printf("-1\n");
		}
	}


	return 0;
}

猜你喜欢

转载自www.cnblogs.com/pixel-Teee/p/13381800.html