1574:マトリックスアクセスゲーム

1574:マトリックスアクセスゲーム

制限時間:1000ミリ秒メモリ制限:524288 KB送信
数:618パス数:248
[タイトルの説明]

私はよくクラスメートと行列アクセスゲームをプレイします:与えられたn×m行列に対して、行列の各要素aijは非負の整数です。ゲームのルールは次のとおりです。

1.数値をフェッチするたびに、各行から1つの要素(合計n)をフェッチし、すべての要素をm回フェッチする必要があります。

2.毎回削除される各要素は、要素が配置されている行の先頭または末尾のみになります。

3.各フェッチのスコアがあります。これは各行のフェッチスコアの合計です。各行のフェッチスコア==削除された要素の値×2i、ここでiは1から数えてi番目のフェッチを表します。 。

4.ゲーム終了時の合計スコアは、m回のスコアの合計です。

私はあなたにプログラムを書くのを手伝って欲しいです、どんなマトリックスについても、あなたは数を取った後に最大のスコアを見つけることができます。

[入力]
入力にはn + 1行が含まれます。最初の行で2つのスペースで区切られた正の整数n、mm次のn行のそれぞれでスペースで区切られた整数。

[出力]
出力は整数です。これは、入力行列が取得された後の最大スコアです。

[入力サンプル]
2 3
1 2 3
2 3 4
[出力サンプル]
82
[プロンプト]
サンプル説明1

1回目:最初の行は行の最初の要素を取り、2番目の行は最後の要素を取ります。今回のスコアは1×21 + 2×21 = 6です。

2回目:両方の行の最初の要素を取得します。今回のスコアは2×22 + 3×22 = 20です。

3回目:今回のスコアは3×23 + 4×23 = 56で、合計スコアは6 + 20 + 56 = 82です。

サンプル入力2

1 4
4 5 05
サンプル出力2

122
サンプル入力3

2 10
96 56 54 46 86 12 23 88 80 43
16 95 18 29 30 53 88 83 6467
サンプル出力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;
}

おすすめ

転載: blog.csdn.net/weixin_52308504/article/details/114077701