若只有一排,则与抓牌游戏相似。
本题不过多次重复。
注意:此题若不用高精度,则会超出范围。
#include<ctime>
#include<cstdio>
#include<algorithm>
using namespace std;
FILE *fin=fopen("game.in","r"),*fout=fopen("game.out","w");
struct bigint
{
int a[32];
bigint()
{
for (int i=0;i<32;i++)
a[i]=0;
}
bigint operator*(const int x)const
{
bigint r;
int s=0;
for (int i=0;i<32;i++)
{
s+=a[i]*x;
r.a[i]=s%10;
s/=10;
}
return r;
}
bool operator<(const bigint &b)const
{int i;
for(i=31;i>0;i--)
if(a[i]!=b.a[i])
break;
return a[i]<b.a[i];
}
void print(FILE *fout)
{
int l;//用来定最高位有效数字
for(l=31;l>0 && a[l]==0;l--);
for(int i=l;i>=0;i--)
fprintf(fout,"%d",a[i]);
}
bigint operator+(const bigint &b)const
{
bigint r;
int s=0;
for (int i=0;i<32;i++)
{
s+=a[i]+b.a[i];
r.a[i]=s%10;
s/=10;
}
return r;
}
};
int a[81];
bigint F[81][81];
bigint c,d;
bigint f(int i,int j,bigint k)
{
bigint u,v;
if(!(F[i][j]<d))//d=0
return F[i][j];
if(i==j)
return F[i][j]=k*a[i];//没有乘法交换律
if((u=k*a[i]+f(i+1,j,k*2))<(v=k*a[j]+f(i,j-1,k*2)))
return F[i][j]=v;
else
return F[i][j]=u;
}
bigint ans;
int main()
{int tt=clock();
c.a[0]=2;//定义初值2
int m,j,n,i;
fscanf(fin,"%d%d",&n,&m);
for(i=0;i<n;i++)
{
for(int i=1;i<=m;i++)//初始化F为负数
for(j=i;j<=m;j++)
F[i][j].a[31]=-1;
for(j=1;j<=m;j++)
fscanf(fin,"%d",a+j);
ans=ans+f(1,m,c);
}
ans.print(fout);
return 0;
}
结果:
测试点#1.in 结果: 内存使用量: 940kB 时间使用量: 2ms最慢888ms。
测试点#2.in 结果: 内存使用量: 944kB 时间使用量: 1ms
测试点#3.in 结果: 内存使用量: 940kB 时间使用量: 1ms
测试点#4.in 结果: 内存使用量: 1072kB 时间使用量: 4ms
测试点#5.in 结果: 内存使用量: 1068kB 时间使用量: 47ms
测试点#6.in 结果: 内存使用量: 1072kB 时间使用量: 52ms
测试点#7.in 结果: 内存使用量: 1072kB 时间使用量: 96ms
测试点#8.in 结果: 内存使用量: 1068kB 时间使用量: 172ms
测试点#9.in 结果: 内存使用量: 1072kB 时间使用量: 679ms
测试点#10.in 结果: 内存使用量: 1072kB 时间使用量: 888ms