华师一附中OI组
标题:
P1005 矩阵取数游戏
[打印本页]
作者:
admin
时间:
2018-7-4 23:39
标题:
P1005 矩阵取数游戏
题目描述
帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的 n×m 的矩阵,矩阵中的每个元素 ai,j均为非负整数。游戏规则如下:
每次取数时须从每行各取走一个元素,共 n个。经过 m 次后取完矩阵内所有元素;
每次取走的各个元素只能是该元素所在行的行首或行尾;
每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值 ×2^i ,其中 i 表示第 i 次取数(从 1 开始编号);
游戏结束总得分为 m 次取数得分之和。
帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。
输入输出格式
输入格式:
输入文件包括 n+1 行:
第 1行为两个用空格隔开的整数 n 和 m 。
第 2~n+1 行为n×m 矩阵,其中每行有 m 个用单个空格隔开的非负整数。
输出格式:
输出文件仅包含 1行,为一个整数,即输入矩阵取数后的最大得分。
输入输出样例
输入样例#1:
2 3
1 2 3
3 4 2
输出样例#1:
82
说明
NOIP 2007 提高第三题
数据范围:
60%的数据满足:1≤n,m≤30 ,答案不超过 10^16
100%的数据满足: 1≤n,m≤80 ,ai,j≤1000
作者:
admin
时间:
2018-7-22 12:02
区间DP的经典例子,转移方程如何写是一方面,还有一个是涉及高精度计算,如何做最高效呢? NOIP考题其实都不难,但是要考察知识掌握的熟练程度!
作者:
吴语林
时间:
2018-7-29 19:43
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
#include <set>
using namespace std;
typedef __int128 u128;
u128 ans,f[85][85]={0};
int a[85][85]={0},*b,n,m;
void print(u128 p)
{
if(p) print(p/10), putchar(p%10+'0');
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
for(int h=1;h<=n;h++)
{
b=a[h];
for(int i=0;i<=m;i++)
for(int j=0;j<=m;j++)
f[i][j]=0;
u128 p=1;
for(int l=m-1;l>=0;l--)
{
p+=p;
for(int i=1;i+l<=m;i++)
{
int j=i+l;
f[i][j-1]=max(f[i][j-1],f[i][j]+p*b[j]);
f[i+1][j]=max(f[i+1][j],f[i][j]+p*b[i]);
}
}
u128 res=0;
for(int i=1;i<=m;i++)
res=max(res,f[i][i-1]);
ans+=res;
}
if(ans) print(ans), putchar('\n');
else puts("0");
return 0;
}
复制代码
作者:
倚窗倾听风吹雨
时间:
2018-10-2 15:47
本帖最后由 倚窗倾听风吹雨 于 2018-10-2 15:49 编辑
打高精做法。毕竟noip不让用__int128,调了一个中午,难受。
#include<iostream>
#include<cstring>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define ROF(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int M=100;
int n,m,jz[M][M][M],f[M][M][M],er[M][M],ans[M],A[M],B[M],c[M];
string s;
inline void mul(int *a,int *b)
{
memset(c,0,sizeof(c));
int ex;
FOR(i,1,a[0])
{
ex=0;
FOR(j,1,b[0])
{
c[i+j-1]+=(a[i]*b[j]+ex);
ex=c[i+j-1]/10;
c[i+j-1]%=10;
}
c[i+b[0]]=ex;
}
c[0]=a[0]+b[0];
while(c[0]>1 && !c[c[0]])c[0]--;
FOR(i,0,c[0])a[i]=c[i];
return;
}
inline void add(int *a,int *b)
{
memset(c,0,sizeof(c));
c[0]=max(a[0],b[0]);
FOR(i,1,c[0])
{
c[i]+=a[i]+b[i];
c[i+1]+=c[i]/10;
c[i]%=10;
}
c[0]++;
while(!c[c[0]] && c[0]>1)c[0]--;
FOR(i,0,c[0])a[i]=c[i];
return;
}
inline bool Max(int *a,int *b)
{
while(a[0]>0 && !a[a[0]])a[0]--;
while(b[0]>0 && !b[b[0]])b[0]--;
if(a[0]!=b[0])return a[0]>b[0];
ROF(i,a[0],1)if(a[i]!=b[i])return a[i]>b[i];
return true;
}
inline void print(int *a)
{
while(a[0]>1 && a[a[0]]==0)a[0]--;
ROF(i,a[0],1)cout<<a[i];
cout<<endl;
}
int main()
{
cin>>n>>m;
FOR(i,1,n)FOR(j,1,m)
{
cin>>s;
ROF(k,s.size()-1,0)
jz[i][j][++jz[i][j][0]]=s[k]-'0';
}
er[0][0]=1;er[0][1]=1;
FOR(i,1,m)
{
FOR(j,0,er[i-1][0])er[i][j]=er[i-1][j];
add(er[i],er[i-1]);
///print(er[i]);
}
FOR(i,1,n)
{
memset(f,0,sizeof(f));
FOR(j,1,m)
{
add(f[j][j],jz[i][j]);
///print(f[j][j]);
mul(f[j][j],er[m]);
///print(f[j][j]);
}
FOR(l,1,m-1)
for(int j=1,k=j+l;k<=m;j++,k++)
{
memset(A,0,sizeof(A));
add(A,jz[i][j]);
mul(A,er[m-l]);
add(A,f[j+1][k]);
memset(B,0,sizeof(B));
add(B,jz[i][k]);
mul(B,er[m-l]);
add(B,f[j][k-1]);
///print(A);print(B);
if(Max(A,B))FOR(o,0,A[0])f[j][k][o]=A[o];
else FOR(o,0,B[0])f[j][k][o]=B[o];
}
///print(f[1][m]);
add(ans,f[1][m]);
}
print(ans);
return 0;
}
复制代码
欢迎光临 华师一附中OI组 (http://hsyit.cn/)
Powered by Discuz! X3.2