TopCode SRM 546: StrllRec_字符字典序剪枝
2012-07-13 22:01
447 查看
Problem Statement | ||||||||||||
For a given string S of length n an inversion is a pair of integers (i, j) such that 0 <= i < j <= n-1 and S[i] > S[j]. (That is, the character at 0-based index i is greater than the character at 0-based index j.) For example, the string "abcab" has 3 inversions: (1, 3), (2, 3), and (2, 4). Given are ints n and minInv, and a string minStr. We will consider all strings that are permutations of the first n lowercase English letters. That is, these strings have length n and contain each of the first n letters exactly once. Out of these strings, return the lexicographically smallest string R with the following two properties: The number of inversions in R is at least minInv. The string R is not lexicographically smaller than minStr. If there is no such string, return an empty string instead. | ||||||||||||
Definition | ||||||||||||
| ||||||||||||
Notes | ||||||||||||
- | A string A is lexicographically smaller than a string B if A is a prefix of B or A contains a smaller character at the first position where the strings differ. | |||||||||||
Constraints | ||||||||||||
- | n will be between 1 and 20, inclusive. | |||||||||||
- | minInv will be between 0 and n*(n-1)/2, inclusive. | |||||||||||
- | minStr will contain between 1 and n characters, inclusive. | |||||||||||
- | Each character in minStr will be one of the first n lowercase Latin letters. | |||||||||||
- | All characters in minStr will be unique. | |||||||||||
Examples | ||||||||||||
0) | ||||||||||||
| ||||||||||||
1) | ||||||||||||
| ||||||||||||
2) | ||||||||||||
| ||||||||||||
3) | ||||||||||||
| ||||||||||||
4) | ||||||||||||
|
//题意:给你两个数n,minInv和一个字符串minStr。求一个长度为n的字符串str,使它满足str>=minStr,且这个字符串的逆序数>=minInv。如果有多个这样的字符串输出字典序最小的!
//分析:dfs,题目字符长度最大可达到20,暴力dfs复杂度为n!,肯定会超时! 忙了半天用了三个剪枝终于A了。
剪枝1:对于题目给出的字符串minStr,dfs得到的当前字符串str (假设已经长度为p) 需满足 str>=minStr.substr(0,p),即str必须大于minStr的前p个字符r, 否则继续dfs得到的str肯定不满足。
剪枝2:dfs过程中得到str不能每次重新计算它的逆序数,需用变量保存。由于dfs过程中一个个的更新str的字符,所以对于每次dfs加入一个字符 C(表明前面的字符已经确定了) 到str中,计算出n个字符中没有被用过的且比C小的字符的个数,因为没有被用过一定会加在当前字符的后面而又比C小,则为当前更新一个字符str所增加的逆序数val。每次dfs累加。
剪枝3(最重要):在剪枝2的基础上,假设当前一次dfs得到一部分str (个数为p) 的字符,按剪枝2的分析已经可以确定后面的字符不管怎么更新对于前面已经确定的字符来说一定存在逆序数值为val。 而剩余n-p个字符的逆序数的【最大值】可以为(n-p)*(n-p-1)/2 。如果val+(n-p)*(n-p-1)/2 <minInv,则当前dfs肯定不满足。
#line 4 "StrIIRec.cpp" #include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #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 <cctype> #include <string> #include <cstring> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> using namespace std; bool used[30],sign; char s[30],str[30]; void dfs(int p,int n,int minInv,string minStr,int use) //use记录没更新得到一个字符增加的逆序数,2 { int i,j; if(p==n&&use>=minInv&&(string)str>=minStr) // 3 { sign=true; return; } if(use+(n-p)*(n-p-1)/2<minInv) return; for(i=0;i<n;i++) { if(!used[i]) { used[i]=true; str[p]=s[i]; string s1=minStr.substr(0,p); // 1 if(str<s1) { used[i]=false; continue; } int t=0; for(j=0;j<n;j++) //计算更新当前字符后增加的逆序数 if(!used[j]&&(j<str[p]-'a')) t++; dfs(p+1,n,minInv,minStr,use+t); if(sign) return; used[i]=false; // while(i+1<n&&s[i+1]==s[i]) i++; } } } class StrIIRec { public: string recovstr(int n, int minInv, string minStr) { int i; s ='\0'; for(i=0;i<n;i++) s[i]='a'+i; //string 类型的字符串不能直接这样赋值 memset(used,false,sizeof(used)); str ='\0',sign=false; dfs(0,n,minInv,minStr,0); if(!sign) return ""; else return (string)str; } }; // Powered by FileEdit // Powered by TZTester 1.01 [25-Feb-2003] // Powered by CodeProcessor
相关文章推荐
- Topcode SRM 556
- topcode SRM 577 DIV1 EllysRoomAssignmentsDiv1
- topcode srm SRM 557
- topcode SRM 577 DIV2 EllysNewNickname
- topcode SRM 577 DIV2 EllysCoprimesDiv2
- 在ASP.NET下实现数字和字符相混合的验证码(C# Code)
- 第十六周项目二:用指针玩字符串(2):去除字符串str中的特定字符c
- TopCoder SRM 681 Div. 2 Problem 500 - ExplodingRobots (枚举)
- 使用javascript的str和substr方法验证非法字符
- Codeforces Round 40 (Rated for Div. 2) B 字符串 不互用字符字串问题
- 字符串替换 eg: str1="123%s456%s" str2={'a','b','c','d'}(将str1中的%s替换成str2中的字符)替换结果返回为:123a456bcd
- 使用str.setCharAt(位置,'字符'),修改指定索引处的字符
- LintCode:M-最长无重复字符的子串
- Top Secret Microsoft Code
- Today is a Historic Day! All-In-One Code Framework Breaks into Top 20 of CodePlex!
- HDU3753 Alignment of Code【字符串流+输入输出】
- Topcode 599 div2 第一题
- Codeforces Round 40 (Rated for Div. 2) B 字符串 不互用字符字串问题
- 真正根据utf8编码的规律来进行截取的字符的函数,utf8版sub_str
- TopCoder Practice SRMs -- SRM 144 DIV 1 -- 300p