P1005 矩阵取数游戏 区间DP

https://www.luogu.com.cn/problem/P1005
以前做过的一道题,当时当贪心来做的,过不去hh,现在再看很明显的区间DP,
可以发现每一行之间是互相不影响的,所以每行进行一次DP,f[i][j]表示以区间[i,j]来做游戏能得到的最大得分,对于区间[i,j]考虑它与它的子区间的关系,因为每次只取一个数所以只用考虑两端就可以了,所以每个区间就是由两个子区间转移过来的,取i点的话就是从[i+1,j]来的,如果取j点的话就是从[i,j-1]来的,比较两个的最大值就可以了,一大坑点是结果爆ll了,所以得用高精度,想叉了以为得高精乘高精,其实只用高精乘低精就可以了

#include<iostream>
#include<vector>>
using namespace std;
typedef long long ll;
const int N=110;
int n,m,a[N][N];
vector<int> po[N],f[N][N];
vector<int> add(vector<int> A, vector<int> B)
{
    if (A.size() < B.size()) return add(B, A);
    vector<int> C;
    int t = 0;
    for (int i = 0; i < A.size(); i ++ )
    {
        t += A[i];
        if (i < B.size()) t += B[i];
        C.push_back(t % 10);
        t /= 10;
    }
    if (t) C.push_back(t);
    return C;
}
vector<int> mul(vector<int> &A, int b)
{
    vector<int> C;
    int t = 0;
    for (int i = 0; i < A.size() || t; i ++ )
    {
        if (i < A.size()) t += A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }
    return C;
}
vector<int> mx(vector<int> x,vector<int> y)
{
	if(x.size()>y.size()) return x;
	if(x.size()<y.size()) return y;
	for(int i=x.size()-1;i>=0;i--)
		if(x[i]>y[i]) return x;
		else if(x[i]<y[i]) return y;
	return x;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			scanf("%d",&a[i][j]);
	po[0].push_back(1);
	for(int i=1;i<=m;i++) po[i]=mul(po[i-1],2);//预处理2的次方
	vector<int>  ans;
	for(int k=1;k<=n;k++)//分行处理
	{
		for(int len=1;len<=m;len++)//枚举长度
		{
			for(int i=1;i+len-1<=m;i++)
			{
				int l=i,r=i+len-1;//区间左右端点
				f[l][r]=add(mul(po[m-len+1],a[k][l]),f[l+1][r]);
				f[l][r]=mx(add(mul(po[m-len+1],a[k][r]),f[l][r-1]),f[l][r]);
			}
		}
		ans=add(f[1][m],ans);
	}
	for(int i=ans.size()-1;i>=0;i--) printf("%d",ans[i]);
	return 0;
}
发布了26 篇原创文章 · 获赞 3 · 访问量 602

猜你喜欢

转载自blog.csdn.net/qq_45288870/article/details/104678373
今日推荐