讨论 / 矩阵取数居然超时了2个点,谁能帮我优化!!
cth 2008-08-29 06:38:00
点我顶贴 收藏 删除
DP+高精度了,超时2个点。我曾经把高精度乘法用的第3个存储结果的变量b都删了,还是超。

#include<stdio.h>

struct big

{

int h[31];

int w;

}best[81];

int n,m,g[81][81];

void print(big a)

{

int i;

printf("%d",a.h[a.w]);

for(i=a.w-1;i>=1;i--)

{

if(a.h[i]<1000)

printf("0");

if(a.h[i]<100)

printf("0");

if(a.h[i]<10)

printf("0");

printf("%d",a.h[i]);

}

}

big clear()

{

big t;

int i;

for(i=0;i<=30;i++)

t.h[i]=0;

t.w=1;

return t;

}

big add(big a,big b)

{

int i,j;

big c=clear();

for(i=1;i<=30;i++)

c.h[i]=a.h[i]+b.h[i];

for(i=1;i<=30;i++)

{

c.h[i+1]+=c.h[i]/10000;

c.h[i]%=10000;

}

for(i=30;i>=1;i--)

if(c.h[i]!=0)

{

c.w=i;

break;

}

return c;

}

big cheng(int a,int k)

{

big b,mi;

int i,j,t;

b=clear(),mi=clear();

mi.h[1]=1;

for(i=1;i<=k;i++)

{

for(j=1;j<=mi.w;j++)

mi.h[j]*=2;

for(j=1;j<=mi.w;j++)

{

mi.h[j+1]+=mi.h[j]/10000;

mi.h[j]%=10000;

}

if(mi.h[mi.w+1]!=0)

mi.w++;

}

for(i=1;i<=mi.w;i++)

b.h[i]=mi.h[i]*=a;

for(i=1;i<=mi.w;i++)

{

b.h[i+1]+=b.h[i]/10000;

b.h[i]%=10000;

}

if(b.h[mi.w+1]!=0)

b.w=mi.w+1;

else

b.w=mi.w;

return b;

}

int compare(big a,big b)

{

int i;

if(a.w>b.w)

return 1;

else if(a.w<b.w)

return 0;

for(i=a.w;i>=1;i--)

{

if(a.h[i]>b.h[i])

return 1;

else if(a.h[i]<b.h[i])

return 0;

}

return 1;

}

big dp(int id)

{

int i,j,k,temp[81];

big max[81][81],a,b;

for(i=1;i<=m;i++)

temp[i]=g[id][i];

for(i=1;i<=80;i++)

for(j=1;j<=80;j++)

max[i][j]=clear();

for(i=1;i<=m;i++)

max[i][1]=cheng(temp[i],m);

for(j=2;j<=m;j++)

{

for(i=1;i<=m-j+1;i++)

{

max[i][j]=cheng(temp[i],m-j+1);

max[i][j]=add(max[i][j],max[i+1][j-1]);

a=cheng(temp[i+j-1],m-j+1);

a=add(a,max[i][j-1]);

if(compare(a,max[i][j]))

{

for(k=1;k<=30;k++)

max[i][j].h[k]=a.h[k];

max[i][j].w=a.w;

}

}

}

return max[1][m];

}

int main()

{

int i,j;

big a;

scanf("%d %d\n",&n,&m);

for(i=1;i<=n;i++)

{

for(j=1;j<=m;j++)

scanf("%d ",&g[i][j]);

scanf("\n");

}

for(i=1;i<=n;i++)

best[i]=clear();

a=clear();

for(i=1;i<=n;i++)

best[i]=dp(i);

for(i=1;i<=n;i++)

a=add(a,best[i]);

print(a);

printf("\n");

}

#1 世纪末的魔术师@2008-08-15 21:41:00
回复 删除
呃。。优化的事要自己做d。。。建议去学学c++的运算符重载,可以使高精度运算方便很多。。。
#2 世纪末的魔术师@2008-08-15 21:41:00
回复 删除
呃。。优化的事要自己做d。。。建议去学学c++的运算符重载,可以使高精度运算方便很多。。。
#3 guoshi3@2008-08-28 19:56:00
回复 删除
ls说具体点。不用讲运算符重载,这我会。你说怎么使高精度简便就行。谢了
#4 guoshi3@2008-08-28 19:58:00
回复 删除
噢,我大概懂了
#5 guoshi3@2008-08-29 06:38:00
回复 删除
不少地方可以优化呢。比如int h[31]这里,优化到int h[10]应该可以把。我在自己机子上测第九个点的时候,一开始开的100位,结果3s过,后来改成10位,半秒就过。这里可能能小优化下。

还有就是每个数的初值,没必要把每一位都设成0吧。把个位设成0就行,因为还存着长度呢,长度为1的话别的数没用的。不过你是图高加方便是吧,你的高加是每一位的加,我觉得还是添0然后加快写。毕竟从初始化到高加的过程都少不少运算。

这个每行可以单独算。所以你的best[i]可以改为best就行,g[i][j]改成g[i]就行。算完一行加一行的数。

我还用了个小优化,就是用到2的50次方一下的数的时候,用int64存,乘的时候就不用高成单了,直接乘即可。加到max[][]里的时候相当于高加单。不过这个优化不是决定性的。把我从两点超时拯救的决定性的还是那个100位变10位....

耐心的慢慢优化吧...一点一点来。我也忙活了半天

查看更多回复
提交回复