PAT1038
题目链接:http://pat.zju.edu.cn/contests/pat-a-practise/1038
基于贪心策略(应该是吧.....):首先按照string类型的比较 从大到小排序,肯定首字母不相同且顺序最大的就应该在最低位,以题给的例子为例 32 321 3214 0229 87 这个数字,排序后从大到小为87 3214 321 32 0229 那么最低位肯定是87了,最主要的问题就是分析如何放置3214 321 32 这几个数字,321是3214的顶头真子串(我自己这样叫的。。), 32又是321 3214的顶头真子串。
应对策略如下:例如先把87放到位,然后取3214,不是87的顶头真子串,所以放在87之前,接下来取321, 321是3214的顶头真子串,所以接下来问题就是考虑321是放在3214之前还是之后,我是这样考虑的,因为321是3214的顶头真子串,所以放在之前之后影响整个数大小的原因是第321的长度+1位,例如若放在3214之前,第4位(321长度为3嘛)为3, 放在3214之后,第4位为4,所以应该放在3214之前。接下来看32的放置,32是321的顶头真子串,所以基于上述策略分析,32应在321之后,继续,32又是3214的顶头真子串,分析后应该放在3214之后,接下来32与87就没什么好说的了,不是顶头真子串,肯定在之前啦。
这里说下为什么要非要是真子串,如果有A与B相同了,那么A放在B之前之后,第A.length+1位都是一样的,但是对于后面就不一定了,所以要接着分析其后的,最终确定位置。
策略就是这样,我用了list容器来放结果,便于插入嘛。 题目最后说前面的最前端的0不要输出,控制下就好。
1 #include<string> 2 #include<iostream> 3 #include<vector> 4 #include<algorithm> 5 #include<list> 6 using namespace std; 7 8 9 int main() 10 { 11 int N; 12 while(cin>>N) 13 { 14 vector<string> v(N); 15 for(int i=0; i<N; ++i) 16 cin>>v[i]; 17 sort(v.begin(), v.end()); 18 list<string> outcome; 19 /*从大到小取*/ 20 for(vector<string>::reverse_iterator riter = v.rbegin(); riter != v.rend(); ++riter) 21 { 22 if(outcome.size()==0) 23 outcome.push_back(*riter); 24 else 25 { 26 for(list<string>::iterator iter = outcome.begin(); iter != outcome.end(); ++iter) 27 { 28 /*验证是顶头真子串*/ 29 if(iter->find(*riter) == 0 && iter->size() != riter->size()) 30 { 31 if(iter->at(0) < iter->at(riter->size())) 32 { 33 outcome.insert(iter, *riter); 34 break; 35 } 36 } 37 else 38 { 39 outcome.insert(iter, *riter); 40 break; 41 } 42 } 43 } 44 } 45 bool flag(false); 46 for(list<string>::iterator iter=outcome.begin(); iter!=outcome.end(); ++iter) 47 { 48 /*控制前端0不输出*/ 49 if(!flag) 50 { 51 for(int i=0; i<iter->size(); ++i) 52 if(!flag) 53 { 54 if(iter->at(i) != '0') 55 { 56 cout<<iter->at(i); 57 flag=true; 58 } 59 } 60 else 61 cout<<iter->at(i); 62 } 63 else 64 cout<<*iter; 65 } 66 /*outcome全是0,那最小就是0*/ 67 if(!flag) 68 cout<<0<<endl; 69 else 70 cout<<endl; 71 } 72 return 0; 73 }