题目大意:
输入一个非递增数字序列,甲先取,乙后取。两个人先后取,先达到递增序列则胜。
比如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;
else
cout<<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;
else
cout<<0;
return 0;
}