主题:第53次粗测结果
小黑骑DK [专家分:610] 发布于 2007-05-21 21:16:00
其实这道题我也不知道什么好方法。 crossbow如果看见了,能不能为大家讲一下你的方法 ?
yxs0001的方法我看不大懂。(把程序中的'1'改成'2','0'改成'1'就是题目的要求了) 似乎比别人快.
其余的大都是回溯的办法。
还有一种就是goal00001111和leejqy的方法,用子串去组合,但是结果都不符合要求.
goal00001111: n为150的时候,你的输出的最后6位是123321,明显3和3重复了。
还有就是strcat之前不应该p[0]=0;么?不加这句的话,我这边都是乱码,根本就没有写进去.
leejqy: 定义ch3的时候少了括号 !! 而且没加p[0] = 0;
//长度36的生成的子串
//length:18
//Which:35
//123132312321231213 123132312321231213
还有就是shen08343的代码:
你是想把所有满足条件的串都找出来(用i级生成所有i+1级,再从i+1级里删去不满足条件的)//i级就是长度为i的串
但是v_str_check里,迭代器似乎不能自减吧。C++有些忘了。我运行时那里有错误.
还有size--没有意义的.不明白你为什么要传size。
第一次测试刷去很慢的和错误的。 所说的很慢是当n为四位数(< 5000)时,等了十多秒都没有结果的。进入第二轮测试的大都不到一秒。
使用递归方法的大都慢,而且我n才几千的时候就已经栈溢出了。
这是进入第二轮测试的名单:crystalx hucheng poorb redbullivws yxs0001 雨中飞燕
//附上我的测试代码
[code=c]
//判断一个字符序列里是否有重复的部分 1为不满足条件
int test_str(const char *p, int n)
{
int i = 2;
for (; i<n; i++)
{
if (overlap(p,i) == 1)
{
printf("\nWhich:%d\n", i);
return 1;
}
}
return 0;
}
//判断一个序列是否有连续重复的部分(以第n个字母结束的子串)
int overlap(const char *p, int n)
{
int max = (n+1)/2;//如果有重复部分,则此长度是最大重复长度
int length = 1;
int end1, end2;//两个要比较的子串结尾
for (; length<=max; length++)
{
for (end1=n,end2=n-length; end1>n-length && p[end1]==p[end2]; end1--,end2--)
;//比较两个子串
if (end1 == n-length)//两子串相同,表明有重复
{
printf("\nlength:%d\n",length);
return 1;
}
}
return 0;
}
[/code]
大家如果有什么异议,问题都可以提出来。 第二次测试周末再测。欢迎大家提意见。
还有就是我是新手,不知道什么测试软件好 ? 大家能不能介绍一下 ?
回复列表 (共20个回复)
沙发
雨中飞燕 [专家分:18980] 发布于 2007-05-21 23:53:00
NAME \ N= 10000 20000 30000 40000 50000
----------------------------------------------------
crystalx 1121 5047 11146 22402 TimeOut
hucheng 1542 6769 14851 26247 TimeOut
poorb 1331 5758 13299 24975 TimeOut
redbullivws 1261 5217 12217 22272 TimeOut
yxs0001 0 0 0 0 10
雨中飞燕 1472 5718 12497 22422 TimeOut
不是一般的快啊
板凳
goal00001111 [专家分:4030] 发布于 2007-05-22 08:02:00
一不小心,成大错误!
少写了两个符号,出大糗了!
原:
for (int i=1; i<MAX; )
{
if (flag)//若出现重复字符串,则需要修改数组a的栈顶元素
[color=FF0000]Change(a, i);[/color]
flag = false; //重新赋值表示没有重复
k = rand()%2 + 1;
Create(a, i, a[i-1][k]);//从a[i-1][1]和a[i-1][2]随机选取一个值作为a[i][0]的值
if (Cover(a, ++i))//如果出现连续重复部分则选取另外一个子串
{
Create(a, i-1, a[i-2][3-k]);//若k==1,则3-k==2 ;若k==2,则3-k==1
if (Cover(a, i))//如果两个子串都不可取(出现连续重复),则数组长度减1,修改前一个子串
{
--i;
flag = true;
}
}
}
红色部分改成[color=FF00FF]Change(a, i--);[/color]即可
请楼主再帮忙测试一次
3 楼
小黑骑DK [专家分:610] 发布于 2007-05-22 10:53:00
goal00001111:
你的代码我测试了,能出结果的没有问题。
但是很怪, MAX为1561,N为4680时,结果一闪即现, 但MAX为1571,N为4710时,等了十几秒都不出来。。。 不知道为什么 ?
可能和测试的机器有关, 下午换机器试下。
下面是我的测试程序 (你自己也测一下,换个大点的数看能不能出结果)
#define N 4680
int main()
{
char *p = (char *)malloc(N+10);
unoverlap(N, p);
printf("%d\n", test_str(p,N));
//printf("%s",p);
free(p);
return 0;
}
4 楼
小黑骑DK [专家分:610] 发布于 2007-05-22 10:56:00
还有就是没看你的main(), 所以以为要加p[0]=0;
其实你已经在main()将p初始化了。 不好意思
5 楼
小黑骑DK [专家分:610] 发布于 2007-05-22 11:30:00
换了台机器, 是同一个数。
唯一的解释那就是不能完全由长度为3的子串组成。你的程序陷入了死循环。
到了一定长度以后必须由更短的长度,否则组成不了。如12 13
6 楼
lrn0409 [专家分:130] 发布于 2007-05-22 13:03:00
/*昨天测试了一下,发现我的程序并没出现向楼主所说的出现溢出,虽然我用的是递归回溯法!然后顺便找了几个进入第二次测评的代码,测了几个数据,发现时间上并比其他的差!也叫楼主帮忙测试了一下,他那边还是有错。(他用的是VC2005),我后来又把vc6.0改为了Dev-c++还是没有问题,并且时间上也都不差于其他几个。所以一直很纳闷为什么不同的编译器会出现这么大的差距。有谁帮忙测试一下。
下面是测试代码,要注意 MAX N 的值!
你只要复制这段代码,在主程序中修改要循环的次数
下面这是我在某次中测试大 数据!
把MAX改为30000,N改为20000,编译器改为了
Dev-c++4.9.9.2
循环 50次!
OK!!!
OK!!!
OK!!!
OK!!!
unoverlap1(N,p) time = 123 //我的程序
unoverlap1(N,p) time = 185
unoverlap1(N,p) time = 123
unoverlap1(N,p) time = 153
我不知道为什么我们测的会出现这样不同的结果,
也许你可以尝试一下其他编译器!!
很抱歉,我并不是证明什么,我只是想把问题搞明白。如果有什么打扰之处,请多多包涵!!!
*/
7 楼
lrn0409 [专家分:130] 发布于 2007-05-22 13:04:00
#include<time.h>
#include<iostream>
using namespace std;
#define MAX 30000 //最大的空间N<MAX
#define N 20000 //要生成的个数即 n;
///////////////////////////////////////////////////////////
/*测试代码 用于判定生成的结果是否正确*/
//判断一个序列是否有连续重复的部分(以第n个字母结束的子串)
int overlap(const char *p, int n)
{
int max = (n+1)/2;//如果有重复部分,则此长度是最大重复长度
int length = 1;
int end1, end2;//两个要比较的子串结尾
for (; length<=max; length++)
{
for (end1=n,end2=n-length; end1>n-length && p[end1]==p[end2]; end1--,end2--)
;//比较两个子串
if (end1 == n-length)//两子串相同,表明有重复
{
printf("\nlength:%d\n",length);
return 1;
}
}
return 0;
}
//判断一个字符序列里是否有重复的部分 1为不满足条件
int test_str(const char *p, int n)
{
int i = 2;
for (; i<n; i++)
{
if (overlap(p,i) == 1)
{
printf("\nWhich:%d\n", i);
return 1;
}
}
return 0;
}
////////////////////////////////////////////////
/* 我的代码 */
bool Insert(char *p,int *mark,int cur,int n)
{
bool Fit;
int half=cur/2; //只要比对当前长度的一半就可以了
int dist;
int i,j,last;
char ch; //要存放的字符
/////////////////////////////////////////
for(int k=0;k<3;k++)
{
if(cur==n)
return true;
Fit=true; //用于表示当前值是否符合
ch='1'+k;
last=cur-1;
while(last>=0&&p[last]!=ch)last--; //找到最近的前一个与当前值一样的下标
for(i=last;i>=half && Fit;i=mark[i])
{
dist=cur-i; //当前值与某个相同下标的距离
j=cur-1;
while(j>i && p[j-dist]==p[j])j--; //逐个匹配
if(j<=i) Fit=false; //判断是否符合
}
if(Fit)
{
p[cur]=ch;
mark[cur]=last;
if(Insert(p,mark,cur+1,n)) //不满足则回溯
return true;
}
}
return false;
}
void unoverlap1(int n, char *p) //函数接口
{
if(n>=MAX || n<0)
return ;
int *mark = new int[MAX]; //用于标记与当前值对应的前一个值,相当于指针
memset(mark,-1,MAX);
Insert(p,mark,0,n);
delete []mark;
}
/* 作者:poorb */
int Is_oK(char *base,int top)
{
int p;
int k;
int foot;
if(base[top-1] == base[top])
return 0;
k = (top+1)/2;
for(foot = 2; foot <= k; foot++)
{
for(p = 0 ; p < foot && base[top-p] == base[top-foot-p];p++);
if(p >= foot)
return 0;
}
return 1;
}
void unoverlap2(int n, char *p)
{
int now = 1;
p[0] = '1';
while(now < n)
{
p[now] = '1';
while(!Is_oK(p,now))
{
for(;p[now] == '3';now--);
p[now]++;
}
now++;
}
//printf("%s",p);
}
8 楼
lrn0409 [专家分:130] 发布于 2007-05-22 13:05:00
/////////////////////////// 作者:crystalx ////////////////
bool check(int end,char *p)
{
for(int i = 1; i <= (end + 1)/2; i++ )
{
int j = 0;
for( ; j < i; j++ )
if (p[end - j] != p[end - j - i]) break;
if(j >= i) return false;
}
return true;
}
void unoverlap3(int n, char *p)
{
for(int i = 0; i < n; i++)
{
p[i] ++ ;
while( p[i] <= '3' )
{
if(check(i,p)) break; //可以放这个数字
p[i]++;
}
if(p[i] > '3') //回溯
{
p[i] = '0';
i = i - 2;
}
}
}
///////作者:雨中飞燕/////////////
void unoverlap4(int n, char *p)
{
p[0]='3';p[1]='2';p[2]='1';
//p[3]='2';p[4]='1';p[5]='3';
int n1, nt;
for(n1=3,p[n1]='0',nt=1;n1<n;nt++)//current index
{
int n2=p[n1]+1,fnn=-1;
for(;n2<='3';n2++)//current number
{
int bUse=1;
fnn=-1;
if(n2==p[n1-1])continue;
for(int nm=(n1>>1),n3=n1-2,nn; n3>=nm; n3--) //compare
{
if(p[n3]==n2) //first char the same
{
int n4=1,ne=n1-n3;
nn=-1;
if(fnn==-1)fnn=n3;
for(;n4<ne;n4++) //compare other chars
{
char c=p[n3-n4];
if(c==n2)
{
nn=n3-n4; //mark next first char
for(;n4<ne;n4++)
{
if(p[n3-n4]!=p[n1-n4])break; //if not same then break
}
break;
}
if(p[n3-n4]!=p[n1-n4])break;
}
if(n4>=ne) //the same
{
bUse=0;
break;
}
else //seach next
{
if(nn>=0)n3=nn;
}
}
}
if(bUse==1) //no the same
{
break;
}
}
if(n2<='3') //goto next char
{
p[n1++] = n2;
p[n1]='0';
}
else //go back
{
p[n1--]='0';
//nRedo++;
}
}
p[n]=0;
}
9 楼
lrn0409 [专家分:130] 发布于 2007-05-22 13:06:00
int main(void)
{
char *p=new char[MAX];
time_t startTime;
time_t endTime1,endTime2,endTime3,endTime4;
time(&startTime);
///////////////////////////
for(int i=0;i<50;i++)
{
unoverlap1(N,p);
}
if(test_str(p,N))
{
cout<<"error!!!";
}
cout<<"OK!!!"<<endl;
time(&endTime1);
///////////////////////
for(int i=0;i<50;i++)
{
unoverlap2(N,p);
}
if(test_str(p,N))
{
cout<<"error!!!";
}
cout<<"OK!!!"<<endl;
time(&endTime2);
////////////////////////
for(int i=0;i<50;i++)
{
unoverlap1(N,p);
}
if(test_str(p,N))
{
cout<<"error!!!";
}
cout<<"OK!!!"<<endl;
time(&endTime3);
//////////////////////
for(int i=0;i<50;i++)
{
unoverlap4(N,p);
}
if(test_str(p,N))
{
cout<<"error!!!";
}
cout<<"OK!!!"<<endl;
time(&endTime4);
//////////////////////////
cout << "unoverlap1(N,p) time = " << difftime(endTime1, startTime) << endl;
cout << "unoverlap2(N,p) time = " << difftime(endTime2, endTime1) << endl;
cout << "unoverlap3(N,p) time = " << difftime(endTime3, endTime2) << endl;
cout << "unoverlap4(N,p) time = " << difftime(endTime4, endTime3) << endl;
system("pause");
return 0;
}
10 楼
redbullivws [专家分:40] 发布于 2007-05-22 13:16:00
//我改过之后的,比原来快了点。主要是check()的效太低了。我的测试代码是用的是check4()。
void unoverlap(int n, char *p)
{
char *q = p;
*q = '0';
while (q - p < n)
{
if (++*q > '3')
{
q--;
continue;
}
if (!check4(p, q))
{
*++q = '0';
}
}
*q = '\0';
}
int check4(char *p, char *top)
{
char *left = top;
char *leftTmp, *rightTmp;
if (p == top)
return 0;
do{
while ((--left >= p) && (*left != *top))
NULL;
for (leftTmp=left, rightTmp=top;
(--rightTmp > left) && (*--leftTmp == *rightTmp); )
NULL;
if (rightTmp == left--) //有重复出现
return 1;
}while ((left + left - p + 1) >= top);
return 0; //OK, 无重复
}
我来回复