给定一个初始状态无序的字符串(长度小于15),A、B两人从此串中依次取出一个字符,假设两人都足够理性,若取完后字符串严格递增有序(a[0]<a[1]<a[2]<...<a[n-1]),则此人获胜。
假设A先取,试判定A最终是胜还是负。
如:213,则A胜
222,则A败
2213,则A胜
假设AB都足够聪明,并都以获胜为目标。
思路:
1.在其中一个人获胜时,我们则要修改上一次另一个人的选择;
2.当某一个人穷尽所有想法都无法获胜,则他需要返回到他上一次的选择,采用另一种结果。
原理也就这么简单。
对于c++和java来说,可以使用map或者hash表记录出现的可能字符串,继而记录该字符串是否可以获胜,后面抽签所获得的字符串就可以引用之前的测试结果,从而加快效率。然后由递归,计算各种字符串组合是否可以满足严格递增有序,然后就可以判断A逐个抽出是否可以获胜了。
这里的record记录的是取出一个数字后剩余序列是否可以获胜。
#include <iostream> #include <string> #include <map> using namespace std; map<string, int> record; int dp(string str){ if (record.find(str) != record.end()) { return record[str]; } int i; for (i =1; i < str.size(); i++) { if (str[i-1] >= str[i]) { break; } } if (i == str.size()) { record[str] = 0; return 0; } for ( i= 0; i < str.size(); i++) { if (dp(str.substr(0,i) + str.substr(i+1)) == 0) { break; } } record[str] = (i != str.size()); //1:可以获胜 return record[str]; } int main(){ string str; cin >> str; cout << dp(str) << endl; system("pause"); return 0; }
那么,c则没这些辅助,就得靠自己了。
#include <stdio.h> #include <stdlib.h> #include <string.h> int level=0; int pd(int who, int* data, int n){ //返回向上层数 int k, kk; int *newdata; int curwhook; for(k=0; k<n; k++){ newdata = (int*)malloc(sizeof(int)*(n-1)); if(k==0) memcpy(newdata, data+1, sizeof(int)*(n-1)); else if(k==n-1) memcpy(newdata, data, sizeof(int)*(n-1)); else{ memcpy(newdata, data, sizeof(int)*k); memcpy(newdata+k, data+k+1, sizeof(int)*(n-k-1)); } for(kk=1; kk<n-1; kk++){ //判断剩余序列是否严格递增 if(*(newdata+kk)<=*(newdata+kk-1)) break; } if(kk==n-1){ //序列严格递增 //free(data); //----------- free(newdata); //----------- if(level==0){ //第0层,则可以确定必赢 printf("A win "); system("pause"); exit(0); } else{ //非第0层,返回上一层,让另一个人重新选 level--; return 1; //返回上一个用户 } } else{ //并无严格递增 level++; if(who==0){ //这次是A取的,下一次要B取 if(pd(1, newdata, n-1)==1){ free(newdata); //---------- continue; } else{ //-1 //free(data); //----------- free(newdata); //----------- level--; //------------ return 1; } } else{ if(pd(0, newdata, n-1)==1){ free(newdata); //----------- continue; } else{ //-1 //free(data); //----------- free(newdata); //----------- level--; //------------- return 1; } } } } if(k==n){ //穷尽了但找不到,返回同一个用户继续下一次循环 if(level==0) printf("B win "); else{ //free(data); //----------- //free(newdata); //----------- level--; if(level==0){ printf("A win "); system("pause"); exit(0); } return -1; } } } int main(void){ char s[20]; int slen, k, kk; int *data; int budayucnt; if(gets(s)==NULL) return 0; slen = strlen(s); data = (int*)malloc(sizeof(int)*slen); for(k=0; k<slen; k++){ *(data+k) = s[k]-'0'; } pd(0, data, slen); system("pause"); return 0; }