1574:矩陣取數游戲
時間限制: 1000 ms 記憶體限制: 524288 KB
提交數: 618 通過數: 248
【題目描述】
經常和同學玩一個矩陣取數游戲:對于給定的 n×m 的矩陣,矩陣中每個元素 aij 均為非負整數,游戲規則如下:
1、每次取數時必須從每行各取走一個元素,共 n 個,m 次取完所有元素,
2、每次取走的各個元素只能是該元素所在行行首或行尾,
3、每次取數都有一個的分值,為每行取數得分之和,每行取數得分==被取走元素值×2i ,其中 i 表示第 i 次取數,從 1 開始計數,
4、游戲結束時,總得分為 m 次取數得分之和,
想讓你幫忙寫一個程式,對于任意矩陣,可以求出取數后的最大得分,
【輸入】
輸入包括 n+1 行, 第一行兩個空格隔開的正整數 n,m 接下來 n 行每行 m 個用空格隔開的整數,
【輸出】
輸出為一個整數,為所輸入矩陣取數后的最大得分
【輸入樣例】
2 3
1 2 3
3 4 2
【輸出樣例】
82
【提示】
樣例解釋 1
第一次:第一行取行首元素,第二行取行尾元素,本次得分為 1×21+2×21=6;
第二次:兩行均取行首元素,本次得分為 2×22+3×22=20;
第三次:本次得分為 3×23+4×23=56,總得分為 6+20+56=82,
樣例輸入 2
1 4
4 5 0 5
樣例輸出 2
122
樣例輸入 3
2 10
96 56 54 46 86 12 23 88 80 43
16 95 18 29 30 53 88 83 64 67
樣例輸出 3
316994
資料范圍與提示:
對于 60% 的資料,1≤n,m≤30,答案不超過 1016 ;
對于 100% 的資料,1≤n,m≤80,0≤ai,j≤1000,
思路:
有點思維含量的區間dp,與其他模板區間dp不同的是,這個題我們要對每一行進行區間dp處理,并且要高精度w(゚Д゚)w
未加高精:
#include<bits/stdc++.h>
#define ull unsigned long long
#define maxn 105
using namespace std;
ull a[maxn][maxn],f[maxn][maxn];
ull p[maxn],ans=0,n,m;
void work(ull tmp)
{
memset(f,0,sizeof(f));
for(int i=1;i<=m;i++) f[i][i]=a[tmp][i]*p[m];//預處理出如果最后選擇i的值
for(int l=2;l<=m;l++)
{
for(int i=1;i+l-1<=m;i++){
int j=i+l-1;
f[i][j]=max(f[i+1][j]+a[tmp][i]*p[m-l+1],f[i][j-1]+a[tmp][j]*p[m-l+1]);
}
}
ans+=f[1][m];
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
}
p[1]=2;
for(int i=2;i<=m;i++) p[i]=p[i-1]*2;
for(int i=1;i<=n;i++) work(i);//對于每一行進行一次dp
cout<<ans<<'\n';
}
加高精:
#include <bits/stdc++.h>
using namespace std;
const int N=85;
const int L=105,Power=4,Base=10000;
int n,m,a[N];
struct Bignum
{
int a[L];
Bignum(){memset(a,0,sizeof a);}
Bignum(int x)
{
memset(a,0,sizeof a);
while(x) {a[++*a]=x%10; x/=10;}
return;
}
inline void Print()
{
int i;
printf("%d",a[*a]);
for(i=*a-1;i>=1;i--)
{
if(a[i]<1000) putchar('0');
if(a[i]<100) putchar('0');
if(a[i]<10) putchar('0');
printf("%d",a[i]);
}
puts("");
return;
}
inline void Init()
{
memset(a,0,sizeof a);
}
}Bin[N],dp[N][N];
inline bool operator<(const Bignum &p,const Bignum &q)
{
if(p.a[0]!=q.a[0]) return (p.a[0]<q.a[0])?1:0;
int i;
for(i=p.a[0];i>=1;i--) if(p.a[i]!=q.a[i])
{
return (p.a[i]<q.a[i])?1:0;
}
return 0;
}
inline Bignum max(Bignum p,Bignum q)
{
return (p<q)?(q):(p);
}
inline Bignum operator+(const Bignum &p,const Bignum &q)
{
int i;
Bignum ans=p;
for(i=1;i<=q.a[0];i++)
{
ans.a[i]+=q.a[i];
if(ans.a[i]>=Base){ans.a[i+1]+=ans.a[i]/Base; ans.a[i]%=Base;}
}
while(ans.a[ans.a[0]+1]) ans.a[0]++;
return ans;
}
inline Bignum operator*(const Bignum &p,const Bignum &q)
{
int i,j;
Bignum ans;
ans.a[0]=p.a[0]+q.a[0];
for(i=1;i<=p.a[0];i++)
{
for(j=1;j<=q.a[0];j++)
{
ans.a[i+j-1]+=p.a[i]*q.a[j];
if(ans.a[i+j-1]>Base)
{
ans.a[i+j]+=ans.a[i+j-1]/Base;
ans.a[i+j-1]%=Base;
}
}
}
while(!ans.a[ans.a[0]]) ans.a[0]--;
return ans;
}
inline Bignum operator*(const Bignum &p,const int &q)
{
int i;
Bignum ans;
ans.a[0]=p.a[0]+5;
for(i=1;i<=p.a[0];i++)
{
ans.a[i]+=p.a[i]*q;
if(ans.a[i]>Base)
{
ans.a[i+1]+=ans.a[i]/Base; ans.a[i]%=Base;
}
}
while(!ans.a[ans.a[0]]) ans.a[0]--;
return ans;
}
inline Bignum Solve()
{
int i,j;
for(i=1;i<=m;i++)
{
for(j=1;j+i-1<=m;j++)
{
int l=j,r=j+i-1;
dp[l][r]=max(dp[l][r-1]+Bin[m-i+1]*a[r],dp[l+1][r]+Bin[m-i+1]*a[l]);
}
}
// dp[1][m].Print();
return dp[1][m];
}
int main()
{
int i,j;
Bignum ans;
scanf("%d%d",&n,&m);
Bin[0]=Bignum(1);
for(i=1;i<=m;i++) Bin[i]=Bin[i-1]*2;
// for(i=1;i<=m;i++)
// {
// Bin[i].Print();
// }
// puts("");
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++) scanf("%d",&a[j]);
ans=ans+Solve();
}
ans.Print();
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/263917.html
標籤:其他
上一篇:wyh的物品
