Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
这样就不超时了???!!!一定是数据的缘故。必须先从尾部执行判断??!!!我下面给出自己的四个程序。两个TLE,两个AC。但是算法分析下来,时间数量级都是一样的!!!。那么,我最后得出结论:一定是数据的缘故,从后向前判断回溯备用的另一分支少,而从前向后则相反,也就是说剪枝具有方向性??!!!。所以必须先从尾部执行判断??!!! TLE1: #include<cstdio> using namespace std; bool check(char *&sub1,char *&sub2,char *&base,int j,int sub1j,int sub2j){ if(base[j]=='\0')return true; if(sub1[sub1j]!='\0'&&base[j]==sub1[sub1j]) if(check(sub1,sub2,base,j+1,sub1j+1,sub2j)==true) return true; if(sub2[sub2j]!='\0'&&base[j]==sub2[sub2j]) if(check(sub1,sub2,base,j+1,sub1j,sub2j+1)==true) return true; return false;//////////以上IF全假才返回False!!!!!!!!!! } int main(){ int n; char *sub1=new char[201],*sub2=new char[201],*base=new char[401]; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%s %s %s",sub1,sub2,base); if(check(sub1,sub2,base,0,0,0)==true)///////从检查base第一个字符开始 printf("Data set %d: yes\n",i+1); else printf("Data set %d: no\n",i+1); } } AC1: #include<cstdio> #include<string> using namespace std;//这样就不超时了???!一定是数据的缘故。必须先从尾部执行判断??! bool check(char *&sub1,char *&sub2,char *&base,int j,int sub1j,int sub2j){ if(j<0)return true; if(sub1j>=0&&base[j]==sub1[sub1j]) if(check(sub1,sub2,base,j-1,sub1j-1,sub2j)==true) return true; if(sub2j>=0&&base[j]==sub2[sub2j]) if(check(sub1,sub2,base,j-1,sub1j,sub2j-1)==true) return true; return false;//////////以上IF全假才返回False!!!!!!!!!! } int main(){ int n; char *sub1=new char[201],*sub2=new char[201],*base=new char[401]; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%s %s %s",sub1,sub2,base); int j=strlen(base),sub1j=strlen(sub1),sub2j=strlen(sub2);///末尾加一者 if(check(sub1,sub2,base,j-1,sub1j-1,sub2j-1)==true)///////从检查base第一个字符开始 printf("Data set %d: yes\n",i+1); else printf("Data set %d: no\n",i+1); } } TLE2: #include<cstdio> #include<stack> using namespace std;////这却TLE,难道是数组引用不好base[j]!='\0,耗时???看来不是,从前面开始搜查,就是会比从后面慢很多????????! struct next{ int j,sub1j,sub2j; next(int i,int sub1i,int sub2i):j(i),sub1j(sub1i),sub2j(sub2i){}; }; bool check(char *&sub1,char *&sub2,char *&base,int i,int sub1i,int sub2i){///////栈回溯 stack<next*> Stack; int j=0,sub1j=0,sub2j=0; while(j<i){ if(base[j]==sub1[sub1j]&&base[j]==sub2[sub2j]){///备用的另一分支, next *temp=new next(j+1,sub1j,sub2j+1);//因为SUB1的先执行,所以备用为SUB2者 Stack.push(temp); j++;sub1j++;//SUB1的先执行 continue; } if(sub1j<sub1i&&base[j]==sub1[sub1j]){//最后一位的下标为长度减一 j++;sub1j++; continue; } if(sub2j<sub2i&&base[j]==sub2[sub2j]){ j++;sub2j++; continue; } if(Stack.empty()!=true){/////上两if都不是,则跳跃回溯到最近的那个分叉点!!!有一个是则不会执行此语句 j=Stack.top()->j;sub1j=Stack.top()->sub1j;sub2j=Stack.top()->sub2j; Stack.pop(); } else break;///都不是,也没有备用的另一分支可回溯,则不可也 } if(j>=i)return true; else return false; } int main(){ int n; char *sub1=new char[201],*sub2=new char[201],*base=new char[401]; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%s %s %s",sub1,sub2,base); int j=strlen(base),sub1j=strlen(sub1),sub2j=strlen(sub2);///末尾加一者,长度!!! if(check(sub1,sub2,base,j,sub1j,sub2j)==true)///////从检查base第一个字符开始 printf("Data set %d: yes\n",i+1); else printf("Data set %d: no\n",i+1); } } AC2: #include<cstdio> #include<stack> using namespace std;///剪枝相对于回溯以及栈写的回溯,只用在检查不成功时才出栈,而并非每次检查都出栈!!!!! struct next{///仅是分叉点,跳跃回溯处,两个都相等,记录而已 int j,sub1j,sub2j; next(int i,int sub1i,int sub2i):j(i),sub1j(sub1i),sub2j(sub2i){}; }; bool check(char *&sub1,char *&sub2,char *&base,int j,int sub1j,int sub2j){///////从后面向前,则不是和第一个末尾相等就要和第二个。否则No,是为剪枝!!!! stack<next*> Stack; while(j>=0){ if(base[j]==sub1[sub1j]&&base[j]==sub2[sub2j]){///备用的另一分支, next *temp=new next(j-1,sub1j,sub2j-1);//因为SUB1的先执行,所以备用为SUB2者 Stack.push(temp); j--;sub1j--;//SUB1的先执行 continue; } if(sub1j>=0&&base[j]==sub1[sub1j]){ j--;sub1j--; continue; } if(sub2j>=0&&base[j]==sub2[sub2j]){ j--;sub2j--; continue; } if(Stack.empty()!=true){/////上两if都不是,则回溯到最近的那个分叉点!!!有一个是则不会执行此语句 j=Stack.top()->j;sub1j=Stack.top()->sub1j;sub2j=Stack.top()->sub2j;//// Stack.pop(); } else break;////都不是,也没有备用的另一分支可回溯,则不可也 } if(j<0)return true; else return false;//////////以上IF全假才返回False!!!!!!!!!! } int main(){ int n; char *sub1=new char[201],*sub2=new char[201],*base=new char[401]; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%s %s %s",sub1,sub2,base); int j=strlen(base),sub1j=strlen(sub1),sub2j=strlen(sub2);///末尾加一者 if(check(sub1,sub2,base,j-1,sub1j-1,sub2j-1)==true)///////从检查base第一个字符开始 printf("Data set %d: yes\n",i+1); else printf("Data set %d: no\n",i+1); } } Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator