Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

这样就不超时了???!!!一定是数据的缘故。必须先从尾部执行判断??!!!

Posted by 2008fanyanjun2008 at 2009-12-30 14:15:52 on Problem 2192
我下面给出自己的四个程序。两个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:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator