华为so-胜负猜想 动态规划复习

来源:互联网 发布:单片机是什么 编辑:程序博客网 时间:2024/05/22 00:29

题目大意:

输入一个非递增数字序列,甲先取,乙后取。两个人先后取,先达到递增序列则胜。

比如213,甲取1,剩下23则胜。

比如222,甲取2,乙取2,剩下2,则乙取胜

甲胜则输出1,输则输出0;


1、比较直接的方法,从前往后遍历,遇到一个逆序就去解决了,比如213,21出现逆序,解决了他!

一种可能是删了2(删了前面大的),一种是删了1(后面小的)。

接下来递归,终点是序列严格递增。

我们需要最后序列最长的最为判定条件。(其实这就转化为最长子序列的问题了)


和原先序列长度的差值就是需要删的个数,就能判定输赢问题。


先是用递归完成的

#include <iostream>#include <string>using namespace std;bool IsUp(string str){if(str.size()==1)return true;for(int i=0;i<str.size();++i)for(int j=i+1;j<str.size();++j)if(str[j]<=str[i])return false;return true;}int maxlen = 0;void dfs (string str){if (IsUp(str)){if(str.size()>maxlen) maxlen = str.size();return;}string temp1;string temp2;for(int i=1; i<str.size(); ++i){if (str[i]<=str[i-1]){temp1.append(str.begin(),str.begin()+i-1);temp1.append(str.begin()+i,str.end());temp2.append(str.begin(),str.begin()+i);temp2.append(str.begin()+i+1,str.end());break;}}//找到递减点,总是删除前面大的或者后面小的cout<<"temp1b:"<<temp1<<endl;dfs(temp1);cout<<"temp1a:"<<temp1<<endl;cout<<"temp2b:"<<temp2<<endl;dfs(temp2);cout<<"temp2a:"<<temp2<<endl;}int main(){string str = "3412";int slen = str.length();dfs(str);if((slen-maxlen)%2==1)cout<<1<<endl;elsecout<<0<<endl;return 0;}


2、动态规划实现(完成最长子序列问题)

状态转移关系式

d[i]为状态数组

d(i) = max{1, d(j)+1},其中j<i,Str[j]<=Str[i]
#include <iostream>#include <string>using namespace std;int win(string str){int *dp = new int[str.size()];int len = 0;memset(dp,1,str.size()*sizeof(int));for (int i=0;i<str.size();++i){for(int j=0;j<i;++j)if(str[j]<str[i] && dp[j]+1>dp[i])dp[i] = dp[j]+1;if(dp[i]>len) len = dp[i];}delete dp;return len;}int main(){string str;cin>>str;if((str.size()-win(str))%2==1)cout<<1;elsecout<<0;return 0;}


0 0
原创粉丝点击