E - Generate a String dp

本文探讨了一个有趣的问题:如何帮助zscoder找到生成特定数量字母'a'字符串的最短时间。通过使用动态规划的方法,我们提供了两种可能的操作路径,并确定了完成任务所需的最少时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

zscoder wants to generate an input file for some programming competition problem.

His input is a string consisting of n letters 'a'. He is too lazy to write a generator so he will manually generate the input in a text editor.

Initially, the text editor is empty. It takes him x seconds to insert or delete a letter 'a' from the text file and y seconds to copy the contents of the entire text file, and duplicate it.

zscoder wants to find the minimum amount of time needed for him to create the input file of exactly n letters 'a'. Help him to determine the amount of time needed to generate the input.

Input

The only line contains three integers nx and y (1 ≤ n ≤ 1071 ≤ x, y ≤ 109) — the number of letters 'a' in the input file and the parameters from the problem statement.

Output

Print the only integer t — the minimum amount of time needed to generate the input file.

Sample Input

Input
8 1 1
Output
4
Input
8 1 10
Output

8

思路:

在处理这个问题时要用到的dp,首先考虑最后一步

如果是偶数的话有两种情况

1.dp[i]=dp[i-1]+x;

2.dp[i]=dp[i/2]+y;

取两者的最xiaoz

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include<math.h> #define MAX_WORDS 1000 #define MAX_WORD_LEN 50 #define DICT_FILE "dictionary.txt" // 计算编辑距离的动态规划函数 int editdistDP(const char *str1, const char *str2) { int m = strlen(str1); int n = strlen(str2); int dp[m+1][n+1]; int i,j; for (i = 0; i <= m; i++) { for (j = 0; j <= n; j++) { if (i == 0) dp[i][j] = j; else if (j == 0) dp[i][j] = i; else if (str1[i-1] == str2[j-1]) dp[i][j] = dp[i-1][j-1]; else dp[i][j] = 1 + (dp[i][j-1] < dp[i-1][j] ? (dp[i][j-1] < dp[i-1][j-1] ? dp[i][j-1] : dp[i-1][j-1]) : (dp[i-1][j] < dp[i-1][j-1] ? dp[i-1][j] : dp[i-1][j-1])); } } return dp[m][n]; } // 加载词典 int loadDictionary(char dictionary[MAX_WORDS][MAX_WORD_LEN]) { FILE *file = fopen(DICT_FILE, "r"); if (!file) return 0; int count = 0; while (count < MAX_WORDS && fscanf(file, "%s", dictionary[count]) != EOF) { count++; } fclose(file); return count; } // 生成2-gram特征向量 void generate2Gram(const char *word, int *vector) { memset(vector, 0, 26*26*sizeof(int)); int i; for (i = 0; word[i] && word[i+1]; i++) { if (isalpha(word[i]) && isalpha(word[i+1])) { int idx = (tolower(word[i]) - 'a') * 26 + (tolower(word[i+1]) - 'a'); vector[idx]++; } } } // 计算2-gram相似度 float calculate2GramSimilarity(const int *vec1, const int *vec2) { int dot = 0, mag1 = 0, mag2 = 0; int i; for (i = 0; i < 26*26; i++) { dot += vec1[i] * vec2[i]; mag1 += vec1[i] * vec1[i]; mag2 += vec2[i] * vec2[i]; } return mag1 * mag2 ? (float)dot / (sqrt(mag1) * sqrt(mag2)) : 0; } // 查找最佳匹配 void findBestMatches(const char *word, char dictionary[MAX_WORDS][MAX_WORD_LEN], int dict_size) { int min_edit = 1000; char best_matches[MAX_WORDS][MAX_WORD_LEN]; int match_count = 0; float best_similarity = -1; int word_vec[26*26]; int best_idx = -1; generate2Gram(word, word_vec); // 第一轮:找最小编辑距离的候选词 int i; for (i = 0; i < dict_size; i++) { int dist = editdistDP(word, dictionary[i]); if (dist < min_edit) { min_edit = dist; match_count = 0; } if (dist == min_edit) { strcpy(best_matches[match_count++], dictionary[i]); } } // 第二轮:用2-gram找出最相似的候选词 for (i = 0; i < match_count; i++) { int candidate_vec[26*26]; generate2Gram(best_matches[i], candidate_vec); float similarity = calculate2GramSimilarity(word_vec, candidate_vec); if (similarity > best_similarity) { best_similarity = similarity; best_idx = i; } } // 输出结果 if (min_edit == 0) { printf("√ 单词正确: %s\n", word); } else if (match_count > 0) { printf("? 建议修正 '%s' -> '%s' (编辑距离: %d, 相似度: %.2f)\n", word, best_matches[best_idx], min_edit, best_similarity); printf(" 其他备选: "); for (i = 0; i < match_count; i++) { if (i != best_idx) printf("%s ", best_matches[i]); } printf("\n"); } else { printf("? 未找到建议: %s\n", word); } } int main() { char dictionary[MAX_WORDS][MAX_WORD_LEN]; int dict_size = loadDictionary(dictionary); if (dict_size == 0) { printf("错误:无法加载词典\n"); return 1; } char input_word[MAX_WORD_LEN]; printf("输入单词 (CTRL+D退出): "); while (scanf("%s", input_word) == 1) { findBestMatches(input_word, dictionary, dict_size); printf("输入单词 (CTRL+D退出): "); } return 0; } dict.txt 是那个字典的文件名,你能帮我改一下代码吗?
最新发布
06-05
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define MAX_WORDS 1000 #define MAX_WORD_LEN 50 #define DICT_FILE "dictionary.txt" // 计算编辑距离的动态规划函数 int editdistDP(const char *str1, const char *str2) { int m = strlen(str1); int n = strlen(str2); int dp[m+1][n+1]; for (int i = 0; i <= m; i++) { for (int j = 0; j <= n; j++) { if (i == 0) dp[i][j] = j; else if (j == 0) dp[i][j] = i; else if (str1[i-1] == str2[j-1]) dp[i][j] = dp[i-1][j-1]; else dp[i][j] = 1 + (dp[i][j-1] < dp[i-1][j] ? (dp[i][j-1] < dp[i-1][j-1] ? dp[i][j-1] : dp[i-1][j-1]) : (dp[i-1][j] < dp[i-1][j-1] ? dp[i-1][j] : dp[i-1][j-1])); } } return dp[m][n]; } // 加载词典 int loadDictionary(char dictionary[MAX_WORDS][MAX_WORD_LEN]) { FILE *file = fopen(DICT_FILE, "r"); if (!file) return 0; int count = 0; while (count < MAX_WORDS && fscanf(file, "%s", dictionary[count]) != EOF) { count++; } fclose(file); return count; } // 生成2-gram特征向量 void generate2Gram(const char *word, int *vector) { memset(vector, 0, 26*26*sizeof(int)); for (int i = 0; word[i] && word[i+1]; i++) { if (isalpha(word[i]) && isalpha(word[i+1])) { int idx = (tolower(word[i]) - 'a') * 26 + (tolower(word[i+1]) - 'a'); vector[idx]++; } } } // 计算2-gram相似度 float calculate2GramSimilarity(const int *vec1, const int *vec2) { int dot = 0, mag1 = 0, mag2 = 0; for (int i = 0; i < 26*26; i++) { dot += vec1[i] * vec2[i]; mag1 += vec1[i] * vec1[i]; mag2 += vec2[i] * vec2[i]; } return mag1 * mag2 ? (float)dot / (sqrt(mag1) * sqrt(mag2)) : 0; } // 查找最佳匹配 void findBestMatches(const char *word, char dictionary[MAX_WORDS][MAX_WORD_LEN], int dict_size) { int min_edit = 1000; char best_matches[MAX_WORDS][MAX_WORD_LEN]; int match_count = 0; float best_similarity = -1; int word_vec[26*26]; int best_idx = -1; generate2Gram(word, word_vec); // 第一轮:找最小编辑距离的候选词 for (int i = 0; i < dict_size; i++) { int dist = editdistDP(word, dictionary[i]); if (dist < min_edit) { min_edit = dist; match_count = 0; } if (dist == min_edit) { strcpy(best_matches[match_count++], dictionary[i]); } } // 第二轮:用2-gram找出最相似的候选词 for (int i = 0; i < match_count; i++) { int candidate_vec[26*26]; generate2Gram(best_matches[i], candidate_vec); float similarity = calculate2GramSimilarity(word_vec, candidate_vec); if (similarity > best_similarity) { best_similarity = similarity; best_idx = i; } } // 输出结果 if (min_edit == 0) { printf("√ 单词正确: %s\n", word); } else if (match_count > 0) { printf("✗ 建议修正 '%s' -> '%s' (编辑距离: %d, 相似度: %.2f)\n", word, best_matches[best_idx], min_edit, best_similarity); printf(" 其他备选: "); for (int i = 0; i < match_count; i++) { if (i != best_idx) printf("%s ", best_matches[i]); } printf("\n"); } else { printf("✗ 未找到建议: %s\n", word); } } int main() { char dictionary[MAX_WORDS][MAX_WORD_LEN]; int dict_size = loadDictionary(dictionary); if (dict_size == 0) { printf("错误:无法加载词典\n"); return 1; } char input_word[MAX_WORD_LEN]; printf("输入单词 (CTRL+D退出): "); while (scanf("%s", input_word) == 1) { findBestMatches(input_word, dictionary, dict_size); printf("输入单词 (CTRL+D退出): "); } return 0; }帮我改成C11和C99都能运行的
06-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值