1627. Text Messaging Improvement?
Constraints
Time Limit: 1 secs, Memory Limit: 32 MB , Special Judge
Description
On a standard mobile phone the letters are distributed across the keys 2 through 9 as:
| 2 | 3 | |
| ABC | DEF | |
| 4 | 5 | 6 |
| GHI | JKL | MNO |
| 7 | 8 | 9 |
| PQRS | TUV | WXYZ |
To enter the letter C, you press key 2 three times (seeing A-B-C).
The number of keystrokes to enter a letter depends on where it is in the list of letters on its key.
The Flathead Telephone Company (FTC) is considering rearranging the letters on the keys to reduce the average number of keystrokes required to enter names etc. or send text messages. The letters must still appear in alphabetical order on the keys but different numbers of letters may appear on each key and possibly more keys could be used. FTC has several databases of letter frequencies used in different applications. For instance, it might help to move S from the 7 key to the 8 key. They need a program which is given the frequencies of the letters and a number of keys and returns the assignment of letters to keys with the smallest average number of keystrokes using the given frequencies. Each key used must have at least one letter and at most eight letters.
Input
The first line of input contains a single integer N , (1≤N≤1000) which is the number of data sets that follow. Each data set consists of three lines of input. The first line contains a single integer K , (4≤K≤26) , the number of keys which are to be used. The second and third lines contain 13 decimal values each giving the percent frequency of the letters A through Z in order.
Output
For each data set, you should generate one line of output with the following values: The data set number as a decimal integer (start counting at one), the best average number of keystrokes to three decimal places, a space and the letters A through Z, for the best arrangement, in order with a single space at the break between letters on different keys. It is possible that the same input data set may produce different output.
Sample Input
2 8 8.167 1.492 2.782 4.253 12.702 2.228 2.015 6.094 6.966 0.153 0.772 4.025 2.406 6.749 7.507 1.929 0.095 5.987 6.327 9.056 2.758 0.978 2.360 0.150 1.974 0.075 9 1.0 10.0 11.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 10.0 10.0 10.0 10.0 10.0 11.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
Sample Output
1 1.647 AB CD EFG HIJK LM NOPQ RS TUVWXYZ2 1.570 A B CDEFG HIJKLM N OP QR STUV WXYZ
// Problem#: 1627 // Submission#: 3593577 // The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License // URI: http://creativecommons.org/licenses/by-nc-sa/3.0/ // All Copyright reserved by Informatic Lab of Sun Yat-sen University /* * Text messaging solution * by Fred Pickel * October 2008 */ #include <stdio.h> #include <stdlib.h> #include <math.h> #define MAX_PROBS 1000 #define EPS .001 #define ERR .001 char inbuf[512]; int nButtons; double charFreq[26]; double freqDenom; int keyLetterCounts[26]; int ReadDataSet(int index) { int i; if(fgets(&(inbuf[0]), 255, stdin) == NULL) { fprintf(stderr, "read failed on problem %d num buttons\n", index); return -1; } inbuf[511] = 0; if(sscanf(inbuf, "%d", &nButtons) != 1) { fprintf(stderr, "scan failed on problem %d num buttons\n", index); return -2; } if(fgets(&(inbuf[0]), 255, stdin) == NULL) { fprintf(stderr, "read failed on problem %d char freq a-m\n", index); return -3; } inbuf[511] = 0; if(sscanf(inbuf, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf ", &charFreq[0], &charFreq[1], &charFreq[2], &charFreq[3], &charFreq[4], &charFreq[5], &charFreq[6], &charFreq[7], &charFreq[8], &charFreq[9], &charFreq[10], &charFreq[11], &charFreq[12]) != 13) { fprintf(stderr, "scan failed on problem %d char freq a-m\n", index); return -4; } if(fgets(&(inbuf[0]), 255, stdin) == NULL) { fprintf(stderr, "read failed on problem %d char freq n-z\n", index); return -5; } inbuf[511] = 0; if(sscanf(inbuf, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf ", &charFreq[13], &charFreq[14], &charFreq[15], &charFreq[16], &charFreq[17], &charFreq[18], &charFreq[19], &charFreq[20], &charFreq[21], &charFreq[22], &charFreq[23], &charFreq[24], &charFreq[25]) != 13) { fprintf(stderr, "scan failed on problem %d char freq n-z\n", index); return -6; } for(i = 0, freqDenom = 0.0; i < 26; i++) { freqDenom += charFreq[i]; } return 0; } // bestAvg[i][j] = best avg num key presses using i+1 keys to do letters 0 to j double bestAvg[26][26]; // bestLetterCount = num letters on key i+1 to get value in bestAvg int bestLetterCount[26][26]; /* solving: * we start with the first key used and count keystrokes using 1-8 letters * then we look at key 2, for each letter count on key 1 we add more letters on key 2 * choosing the smallest total count etc * */ int TeleSolve() { int i, j, k, lim; double curCount; // init for(i = 0; i < 26; i++) { for(j = 0; j < 26; j++) { bestAvg[i][j] = 5000.0; // bigger than any valid count bestLetterCount[i][j] = 0; } } // do first key for(i = 0, curCount = 0.0; i < 8 ; i++) // max 8 on a key { curCount += (i+1)*charFreq[i]; // cost of another letter on key bestAvg[0][i] = curCount; bestLetterCount[0][i] = i+1; } // now do remaining keys for(j = 1; j < nButtons ; j++) { for(k = j; k < 26; k++) // at least one letter on each prior key { // for each combination of preiously compute sums // start from there with up to 8 keys, choosing best arrangement if(bestAvg[j-1][k-1] > 4000.0) { // cannot be useful, would be more that 8 chars on prior keys break; } lim = 26 - nButtons + j + 1; // cannot go beyond this, leave room for one keys on each later button if(lim > 8) lim = 8; // max 8 on a key for(i = 0, curCount = bestAvg[j-1][k-1]; i < lim ; i++) { // for each possible letter on this key startingwith letter 'A'+k // see what cost of i letters on this key would add, if better than prior, remeber curCount += (i+1)*charFreq[i+k]; if(bestAvg[j][k+i] > curCount) { bestAvg[j][k+i] = curCount; bestLetterCount[j][k+i] = i+1; } } } } return 0; } void PrintSolution(int probNum) { int i, j, k; // scan backwards through the bestLetterCounts array to find out // how many letters on each key for(i = nButtons - 1, j = 25; i >= 0 ; i--) { keyLetterCounts[i] = bestLetterCount[i][j]; j -= keyLetterCounts[i]; } // print prob num and best avg key presses printf("%d %.3f ", probNum, bestAvg[nButtons-1][25]/100.0); // print letters on keys for(i = 0, j=0; i < nButtons ; i++) { for(k = 0; k < keyLetterCounts[i] ; k++) { putchar('A' + j); j++; } putchar(' '); } printf("\n"); } int main() { int probCnt, curProb, ret; if(fgets(&(inbuf[0]), 255, stdin) == NULL) { fprintf(stderr, "read failed on problem count\n"); return -1; } inbuf[255] = 0; probCnt = atoi(&(inbuf[0])); if((probCnt < 1) || (probCnt > MAX_PROBS)) { fprintf(stderr, "Problem count %d not in range 1...%d\n", probCnt, MAX_PROBS); return -2; } for(curProb = 1; curProb <= probCnt ; curProb++) { if((ret = ReadDataSet(curProb)) != 0) { fprintf(stderr, "ReadDataSet returned %d on problem %d\n", ret, curProb); return -3; } TeleSolve(); PrintSolution(curProb); } return 0; }
本文介绍了一种优化标准手机短信输入的算法,通过重新分配字母到按键上,减少平均按键次数。该算法考虑了不同应用场景下字母出现的频率,并提供了一个程序来计算最佳按键分配方案。
448

被折叠的 条评论
为什么被折叠?



