• 刷题记录:牛客NC14701取数游戏2


    传送门:牛客

    题目描述:

    给定两个长度为n的整数列A和B,每次你可以从A数列的左端或右端取走一个数。假设第i次取走的数为ax,则第i次取走的数的价值vi=bi⋅ax,现在希望你求出∑vi的最大值。
    输入:
    2
    2
    1 1000
    2 1
    5
    1 3 5 2 4
    1 2 3 4 5
    输出:
    2001
    52
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    呜呜呜,这可以说是我在刷dp的过程中第一道自己推出的转移方程(虽然很简单但是也给了我信心)

    主要思路:

    1. 对于这一道,我们可以有一个朴素的想法,我们可以使用 d p [ i ] [ j ] dp[i][j] dp[i][j]来记录 一个数列左边取 i 个数字 , 右边取 j 个数字的最大价值 一个数列左边取i个数字,右边取j个数字的最大价值 一个数列左边取i个数字,右边取j个数字的最大价值,那么我们就会发现我们的当我们枚举到 ( i , j ) (i,j) (i,j)时,我们有两种可以到达这种状态的路径,一种是 ( i − 1 , j ) , 左边再取一个 (i-1,j),左边再取一个 (i1,j),左边再取一个, ( i , j − 1 ) , 右边再取一个 (i,j-1),右边再取一个 (i,j1),右边再取一个,并且此时我们一共枚举了 ( i + j ) (i+j) (i+j)个数字,此时我们的贡献值也就不难写出了.

    总结一下我们的dp方程:

    d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] + b [ i + j ] ∗ a [ i ] , d p [ i ] [ j − 1 ] + b [ i + j ] ∗ a [ n − j + 1 ] ) ; dp[i][j]=max(dp[i-1][j]+b[i+j]*a[i],dp[i][j-1]+b[i+j]*a[n-j+1]); dp[i][j]=max(dp[i1][j]+b[i+j]a[i],dp[i][j1]+b[i+j]a[nj+1]);

    并且我们的边界应该是两端点分别都取0的时候,此时我们的值就是一边逐渐累加上去即可

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    typedef long long ll;
    #define inf 0x3f3f3f3f
    #define root 1,n,1
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    inline ll read() {
    	ll x=0,w=1;char ch=getchar();
    	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
    	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    	return x*w;
    }
    #define maxn 1000000
    #define ll_maxn 0x3f3f3f3f3f3f3f3f
    const double eps=1e-8;
    int T;int n;
    ll a[maxn],b[maxn];
    ll dp[1010][1010];
    int main() {
    	T=read();
    	while(T--) {
    		memset(dp,0,sizeof(dp));
    		memset(a,0,sizeof(a));
    		memset(b,0,sizeof(b));
    		n=read();
    		ll ans=-inf;
    		for(int i=1;i<=n;i++) a[i]=read();
    		for(int i=1;i<=n;i++) b[i]=read();
    		for(int i=1;i<=n;i++) {
    			dp[i][0]=dp[i-1][0]+b[i]*a[i];
    			dp[0][i]=dp[0][i-1]+b[i]*a[n-i+1];
    		}
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=n-i;j++) {
    				dp[i][j]=max(dp[i-1][j]+b[i+j]*a[i],dp[i][j-1]+b[i+j]*a[n-j+1]);
    				if(i+j==n) {
    					ans=max(ans,dp[i][j]);
    				}
    			}
    		}	
    		printf("%lld\n",ans);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
  • 相关阅读:
    数据结构-带头双向循环链表(增删查改)(2)
    实验29:循迹传感器实验
    简易实现Spring Framework底层机制
    Vue-ref属性(脚手架获取DOM元素)、props配置、mixin混入、插件、scoped样式
    HarmonyOS 如何使用异步并发能力进行开发
    9.3DDD之集成事件
    如何封装安全的go
    【数据结构】内部排序小结- -基数排序
    pandas使用pd.DateOffset生成时间偏移量、把dataframe数据中的时间数据列统一相减N天、缩小、向前偏移N天
    MySQL的基础(一)
  • 原文地址:https://blog.csdn.net/yingjiayu12/article/details/127654312