1 条题解

  • 0

    解题分析

    11.频率统计:遍历所有单词,统计每个字符出现的总次数。例如,在样例输入11中,"hh"和"ii"各出现11次,"oo"和"kk"各出现11次。

    22.字符排序:将字符按频率降序排序,频率相同的按字符升序排列。这样可以确保高频率字符优先分配,且在频率相同时选择字典序较小的字符。

    33.按键分配:将排序后的字符序列分成1212段,每个按键分配的字符数可以不同,高频率字符应该尽量分配到前面的按键,且在每个按键的字符串中靠前

    44.切割点确定:确定1111个切割点,使得这1111个点之后的字符作为下一个按键的开始字符。

    解题思路

    这个问题需要我们将一个连续的字符序列(标签带)切割成1212段,分配给手机键盘的1212个按键,使得输入词典中所有单词的平均按键次数最少。关键在于:

    11.字符频率统计:首先需要统计词典中每个字符的出现频率,高频字符应该分配在按键序列的前面位置,以减少按键次数。

    22.最优切割策略:将字符按频率降序排序,然后按频率高低依次分配到1212个按键上。高频率字符应该尽量放在按键字符串的前面位置。

    33.字典序处理:当存在多个最优解时,选择字典序最小的切割方案。

    实现步骤

    11.输入处理:读取测试用例数量tt,对于每个测试用例:读取单词数量MM,读取MM个单词,统计每个字符的出现频率。

    22.字符处理:创建包含所有可能字符的集合(az,+,,/,?a-z, +, *, /, ?),统计每个字符的总出现次数,过滤掉频率为00的字符。

    33.排序字符:按频率降序排序,频率相同的按字符升序排列

    44.确定切割点:将排序后的字符序列均匀分配到1212个按键,计算1111个切割点位置,确保切割后的分配方案使平均按键次数最少。

    55.输出结果:提取1111个切割点的字符,按字典序选择最优解,输出结果字符串。

    代码实现

    #include <iostream> 
    #include <cstring> 
    #include <cstdio> 
    using namespace std;
     
    const int N = 32;
     
    char alph[] = " abcdefghijklmnopqrstuvwxyz+*/?";
    int flect[140];
    int num[N];
    int s[N][N];
    int dp[N][N];
    int ans[N];
     
    void init()
    { 
    	for (int i = 1; i <= 30; i++)
    		flect[(int) alph[i]] = i;
    } 
    char str[N];
     
    int main()
    { 
    	//freopen("in.txt", "r", stdin);
    	init();
    	int n, T, i, j, k;
     
    	scanf("%d", &T);
    	while (T--)
    	{
    		scanf("%d", &n);
    		memset(num, 0, sizeof(num));
    		for (i = 0; i < n; i++)
    		{
    			scanf("%s", str);
    			for (j = 0; str[j]; j++)
    				num[flect[(int)str[j]]]++;
    		}
    		//dp
    		memset(dp, 0x3f, sizeof(dp));
    		int sum = 0;
    		for (i = 1; i <= 19; i++)
    		{
    			sum += num[i] * i;
    			dp[1][i] = sum;
    			s[1][i] = 1;
    		}
    		for (i = 2; i <= 12; i++)
    			for (j = i; j <= 30; j++)
    			{
    				for (k = i; k <= j; k++)
    				{
    					sum = 0;
    					for (int h = k; h <= j; h++)
    						sum += num[h] *(h - k + 1);
    					if (dp[i - 1][k - 1] + sum < dp[i][j])
    					{
    						dp[i][j] = dp[i - 1][k - 1] + sum;
    						s[i][j] = k;
    					}
    				}
    			}
    			int cnt = 0;
    			int now = 30;
    			for (i = 12; i > 1; i--)
    			{
    				ans[cnt++] = s[i][now];
    				now = s[i][now] - 1;
    			}
    			for (i = cnt - 1; i >= 0; i--)
    				printf("%c", alph[ans[i]]);
    			printf("\n");
    	}
    	
    }
    • 1

    信息

    ID
    1292
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者