CodeForces 148E – Porcelain

首先解决一个问题:

给一行数,可以从两端拿取,问拿m次后所取的数的和最大是多少?

思路:左边拿多少确定以后,只要枚举一下右边的个数就可以了


代码:

import java.io.*;
import java.util.*;

public class Main {

        public static void main(String[] argv)  throws IOException
        {
        	Scanner in = new Scanner(new BufferedInputStream(System.in));
        	int[] shelf = new int[1000];
        	int[] D = new int[1000];
        	
        	
        	int n = in.nextInt();
        	int num = in.nextInt();
        	
        	for(int i =1 ; i <= n ; i++)
        	{
        		shelf[i] = in.nextInt();
        		shelf[i] += shelf[i-1];		//求和预处理
        	}
        	
        	for(int i = 0 ; i <= n ; i++)		//左边选n-i个之后,右边枚举选j个
        		for(int j = 0 ; j <= i ; j++)
        			D[n-i+j] = Math.max(D[n-i+j] , shelf[n] - shelf[i] + shelf[j]);
        	
        	System.out.println(D[num]);

        }

}



那么本题的思路:

先构造一个小动规D,D[i]记录取i个数时的最大和(首先预处理)

然后构造一个整体dp,dp[i]表示仅考虑前几行时,取i个数得到的最大和

状态转移方程:

                        dp[i][j] = max(dp[i-1][j-k] + D[k]);

我们要枚举的就是k了


总体代码:

import java.io.*;
import java.util.*;

public class Main {
	
	static int[] shelf = new int[10100];
	static int n,m;
	static int[] dp = new int[10100];
	static int[] D = new int[10100];
	

	public static void main(String[] argv)
	{
		Scanner in = new Scanner(new BufferedInputStream(System.in));
		
		n=in.nextInt();
		m=in.nextInt();
		
		for(int i = 1 ; i <= n ; i++)
		{
			int a = in.nextInt();
			
			for(int j=1 ; j <= a ; j++)		
			{
				shelf[j] = in.nextInt();
				shelf[j] += shelf[j-1];			//sum to preprocess
			}
			
			Arrays.fill(D,0);
			
			for(int j = 0 ; j < a ; j++)		//make D,D[x] represent that we break x will make the maximum damage
				for(int k = j ; k <= a ; k++)	//take j from left and,take a-k from the right
					D[a+j-k] = Math.max(D[a+j-k] , shelf[a] + shelf[j] - shelf[k]);
			
			for(int j = m ; j>=1 ; j--)
				for(int k = Math.min(j,a) ; k>=1 ; k--)
					dp[j] = Math.max(dp[j],dp[j-k] + D[k]);	//dp[j] = the front i-1 line berak j-k times and current line break k times  will make the maximum damage 
		}
		
		System.out.println(dp[m]);
	
	}
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值