SRM 617

来源:互联网 发布:知乎 东邪西毒讲的什么 编辑:程序博客网 时间:2024/06/05 19:46

easy:注意consecutive这个词,给同一个人要连续的几段啊。。。。尼玛没有看到啊。。。。然后有了这个词,就可以直接暴力标记那些位置要切。


medium:先把奇数度的点配对,变成个欧拉回路,然后跑一遍,这样不要加的变,每个奇度点才会有1的cost,偶度点都没有,这样显然最小。


hard:长度为25保证总有一个没出现过的字符,这样我们就可以一位一位贪心,每一位靠dp得到上下界(后面没确定的全部设为通配符或者没出现过即全都不匹配,得到上下届,need在上下界这一位就选那个字符),枚举lcs,枚举每一位,枚举每一位选的字母,然后做lcs,总复杂度是n^4*m

(十分感谢safarisoul教会我了n^3*m的做法!她的题解:http://topcoder-algorithm.blogspot.com.au/2014/04/srm517-div1-800-farstrings.html)

#include <vector>#include <list>#include <map>#include <set>#include <deque>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iostream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <ctime>#include <cstring>using namespace std;class FarStrings {public:vector<string> find(string);};int dp[30][30];bool eq(char a, char b) {if (a == 'A')return true;return a == b;}int lcs(string s, string t) {int i, j, k;int n;memset(dp, 0, sizeof(dp));n = s.size();for (i = 0; i <= n; ++i) {dp[i][0] = i;dp[0][i] = i;}for (i = 0; i < n; ++i) {for (j = 0; j < n; ++j) {if (eq(s[i], t[j]))dp[i + 1][j + 1] = dp[i][j];else {dp[i + 1][j + 1] = min(dp[i][j + 1] + 1, min(dp[i + 1][j] + 1,dp[i][j] + 1));}}}return dp[n][n];}vector<string> FarStrings::find(string t) {int i, j, k;vector<string> ret;string s, p;int n;n = t.size();for (i = 1; i <= n; ++i) {s.clear();p.clear();for (j = 0; j < n; ++j) {s.push_back('A');p.push_back('B');}for (j = 0; j < n; ++j) {for (k = 0; k < 26; ++k) {s[j] = k + 'a';p[j] = k + 'a';if (i >= lcs(s, t) && i <= lcs(p, t))break;}}ret.push_back(s);}return ret;}

挖个坑, safarisoul提供了两份资料,貌似能更优?还没来得及看 

http://dl.acm.org/citation.cfm?id=214183
http://link.springer.com/chapter/10.1007%2FBFb0030777

0 0
原创粉丝点击