您的位置:首页 > 其它

wikioi p1166 矩阵取数游戏

2013-08-25 13:13 274 查看
这题是动规还好  问题是要加功能很齐全的高精度   一下子就变得恶心了

高精度没法说.....就不说了...

dp[i][j] 表示计算的那一层还剩下为 [ i , j ] 的区间 保存之前取数的最大值 

首先因为每一层求得最值都互不影响

所以for( res  1->n)枚举每一层的最大值

然后for( k  1->m)枚举第几次取数 同时计算2的k次幂

最后枚举左区间( L  1->k) 因为第k次取数该排最多只能取k个  所以L枚举到k就行了

通过k和L可以计算出右区间端点  R = m + L - 1 - k ;

动规方程为dp[L][R] = max(dp[L - 1][R] + (2^k )* map[res][L - 1], dp[L][R + 1] + (2^k) * map[res][R + 1])

每一层取完数字的最大值就是之前计算的dp[i][j]中的一个最大值 ans = max(dp[i][j] , ans) 

再吧ans累加即可得到答案

一开始看错题目了,以为是总共取M次,谁知道是每次M次,那这题就简单了,没的说。

但是高精度有点烦。

现在终于自己写出来了

/*
Sour : NOIPSenior
ID : Thaddeus
PID : 1005
*/
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<memory.h>
using namespace std;
const int maxn = 81;
const int maxm = 5;
const long long radix = 1000000000;
long long a[maxn][maxn][maxm];
long long f[maxn][maxn][maxn][maxm]; //第i行头取j~k的最大值
long long r[maxn][maxm]; //二进制数
long long ans[maxm];
long long mul1[maxm];
long long mul2[maxm];
long long com1[maxm];
long long com2[maxm];
long long zero[maxm];
long long two[maxm];
long long temp[maxm];
int n,m;
void init()
{
int i,j;
scanf("%d %d",&n,&m);
for (i=1;i<=n;i++)
for (j=1;j<=m;j++)
scanf("%lld",&a[i][j][1]);
}
bool comp(long long x[],long long y[]) //判断数字x是否比y大,如果是,返回true
{
int i;
for (i=maxm-1;i>=1;i--)
{
if (x[i]>y[i]) return true;
if (x[i]<y[i]) return false;
}
return true;
}
void plu(long long x[],long long y[],long long z[]) //将x与y相加的值记录到z中
{
int i;
for (i=0;i<maxm;i++)
z[i]=0;
for (i=1;i<maxm;i++)
{
z[i]+=x[i]+y[i];
z[i+1]+=z[i]/radix;
z[i]%=radix;
}
for (i=1;i<maxm;i++)
z[i]+=z[i-1]/radix,z[i-1]%=radix;
}
void mult(long long x[],long long y[],long long z[])//将x与y相乘的值记录到z中
{
int i,j;
for (i=0;i<maxm;i++)
z[i]=0;
for (i=1;i<maxm;i++)
for (j=1;j<maxm;j++)
if (i+j<=maxm)
{
z[i+j-1]+=x[i]*y[j];
z[i+j]+=z[i+j-1]/radix;
z[i+j-1]%=radix;
}
for (i=0;i<maxm;i++)
{
z[i+1]+=z[i]/radix;
z[i]%=radix;
}
}
void _put(long long x[])
{
int i;
i = maxm-1;
while(!x[i]&&i>1) --i;
printf("%lld",x[i--]);
for (;i>=1;i--)
printf("%09lld",x[i]);
}
void _init()
{
int i;
memset(ans,0,sizeof(ans));
memset(f,0,sizeof(f));
memset(zero,0,sizeof(zero));
memset(two,0,sizeof(two));
memset(r,0,sizeof(r));
two[1]=2;
r[0][1]=1;
for (i=1;i<=m;i++)
mult(r[i-1],two,r[i]);
}
void work()
{
int i,j,k,p;
for (i=1;i<=n;i++)
{
for (j=1;j<=m;j++)
mult(a[i][j],r[m],f[i][j][j]);
for (p=1;p<=m;p++)
for (j=1;j+p<=m;j++)
{
k = p+j;
mult(a[i][j],r[m-p],mul1);
mult(a[i][k],r[m-p],mul2);
plu(mul1,f[i][j+1][k],com1);
plu(mul2,f[i][j][k-1],com2);
if (comp(com1,com2))
plu(com1,zero,f[i][j][k]);
else
plu(com2,zero,f[i][j][k]);
}
}
}
void put()
{
int i;
for (i=1;i<=n;i++)
plu(ans,f[i][1][m],temp),plu(temp,zero,ans);
_put(ans);
}
int main()
{
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
init();
_init();
work();
put();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: