CodeForces 148E Porcelain dp+背包(水

题目链接:点击打开链接

题意:

给定一个n层书架,一共取m本书。

下面n行给出每层书的价值。

每次可以取任意一层的最左端或最右端的一本书。

问能获得的最大价值。

思路:

1、显然是先求出对于每层任取任意本书能获得的最大价值。

2、然后背包一下。

1:

对于一层书任意j本,那么一定是从左端取k本,右端取 j-k本,求个前缀和然后枚举 j和k即可。每层n^2的dp

2:

分组背包。

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Queue;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class Main {
	int m, n;
	int[] sum = new int[N], num = new int[N];
	int[][] dp = new int[N][N], h = new int[2][M];
	void work() throws Exception{
		n = Int(); m = Int();
		for(int i = 1; i <= n; i++){
			num[i] = Int();
			sum[0] = 0;
			for(int j = 1; j <= num[i]; j++){ sum[j] = sum[j-1]+Int(); }
			dp[i][0] = 0;
			for(int j = 1; j <= num[i]; j++){
				dp[i][j] = 0;
				for(int k = 0; k <= j; k++)
					dp[i][j] = max(dp[i][j], sum[k] + sum[num[i]] - sum[num[i]-j+k]);
			}
		}
		int cur = 0, old = 1;
		for(int i = 0; i <= m; i++)h[cur][i] = 0;
		for(int i = 1; i <= n; i++)
		{
			cur ^= 1; old ^= 1;
			for(int j = 0; j <= m; j++)h[cur][j] = h[old][j];
			for(int j = 0; j <= num[i]; j++)
			{
				for(int k = j; k <= m; k++)
					h[cur][k] = max(h[cur][k], h[old][k-j]+dp[i][j]);
			}
		}
		out.println(h[cur][m]);
	}

    public static void main(String[] args) throws Exception{
        Main wo = new Main();
    	in = new BufferedReader(new InputStreamReader(System.in));
    	out = new PrintWriter(System.out);
  //  	in = new BufferedReader(new InputStreamReader(new FileInputStream(new File("input.txt"))));
  //  	out = new PrintWriter(new File("output.txt"));
        wo.work();
        out.close();
    }

	static int N = 101;
	static int M = 10001;
	DecimalFormat df=new DecimalFormat("0.0000");
	static int inf = (int)1e9;
	static long inf64 = (long) 1e18;
	static double eps = 1e-8;
	static double Pi = Math.PI;
	static int mod = (int)1e9 + 7 ;

	private String Next() throws Exception{
    	while (str == null || !str.hasMoreElements())
    	    str = new StringTokenizer(in.readLine());
    	return str.nextToken();
    }
    private int Int() throws Exception{
    	return Integer.parseInt(Next());
    }
    private long Long() throws Exception{
    	return Long.parseLong(Next());
    }
    private double Double() throws Exception{
    	return Double.parseDouble(Next());
    }
    StringTokenizer str;
    static Scanner cin = new Scanner(System.in);
    static BufferedReader in;
    static PrintWriter out;
  /*
	class Edge{
		int from, to, dis, nex;
		Edge(){}
		Edge(int from, int to, int dis, int nex){
			this.from = from;
			this.to = to;
			this.dis = dis;
			this.nex = nex;
		}
	}
	Edge[] edge = new Edge[M<<1];
	int[] head = new int[N];
	int edgenum;
	void init_edge(){for(int i = 0; i < N; i++)head[i] = -1; edgenum = 0;}
	void add(int u, int v, int dis){
		edge[edgenum] = new Edge(u, v, dis, head[u]);
		head[u] = edgenum++;
	}/**/
	int upper_bound(int[] A, int l, int r, int val) {// upper_bound(A+l,A+r,val)-A;
		int pos = r;
		r--;
		while (l <= r) {
			int mid = (l + r) >> 1;
			if (A[mid] <= val) {
				l = mid + 1;
			} else {
				pos = mid;
				r = mid - 1;
			}
		}
		return pos;
	}

	int Pow(int x, int y) {
		int ans = 1;
		while (y > 0) {
			if ((y & 1) > 0)
				ans *= x;
			y >>= 1;
			x = x * x;
		}
		return ans;
	}
	double Pow(double x, int y) {
		double ans = 1;
		while (y > 0) {
			if ((y & 1) > 0)
				ans *= x;
			y >>= 1;
			x = x * x;
		}
		return ans;
	}
	int Pow_Mod(int x, int y, int mod) {
		int ans = 1;
		while (y > 0) {
			if ((y & 1) > 0)
				ans *= x;
			ans %= mod;
			y >>= 1;
			x = x * x;
			x %= mod;
		}
		return ans;
	}
	long Pow(long x, long y) {
		long ans = 1;
		while (y > 0) {
			if ((y & 1) > 0)
				ans *= x;
			y >>= 1;
			x = x * x;
		}
		return ans;
	}
	long Pow_Mod(long x, long y, long mod) {
		long ans = 1;
		while (y > 0) {
			if ((y & 1) > 0)
				ans *= x;
			ans %= mod;
			y >>= 1;
			x = x * x;
			x %= mod;
		}
		return ans;
	}

	int gcd(int x, int y){
		if(x>y){int tmp = x; x = y; y = tmp;}
		while(x>0){
			y %= x;
			int tmp = x; x = y; y = tmp;
		}
		return y;
	}
	int max(int x, int y) {
		return x > y ? x : y;
	}

	int min(int x, int y) {
		return x < y ? x : y;
	}

	double max(double x, double y) {
		return x > y ? x : y;
	}

	double min(double x, double y) {
		return x < y ? x : y;
	}

	long max(long x, long y) {
		return x > y ? x : y;
	}

	long min(long x, long y) {
		return x < y ? x : y;
	}

	int abs(int x) {
		return x > 0 ? x : -x;
	}

	double abs(double x) {
		return x > 0 ? x : -x;
	}

	long abs(long x) {
		return x > 0 ? x : -x;
	}

	boolean zero(double x) {
		return abs(x) < eps;
	}
	double sin(double x){return Math.sin(x);}
	double cos(double x){return Math.cos(x);}
	double tan(double x){return Math.tan(x);}
	double sqrt(double x){return Math.sqrt(x);}
}
时间: 2024-08-06 19:47:01

CodeForces 148E Porcelain dp+背包(水的相关文章

Codeforces 148E Porcelain [预处理+dp背包]

给出n行数,每行的数目不定(不超过100个),只能从行的两端取数m次,求所取数的和最大值 n (1?≤?n?≤?100) andm (1?≤?m?≤?10000). 看似很难上手 我甚至想每次取一个,然后搜索,,,搜索分支有200个 如果我们知道每行取k个最多能取多少的话 那么 这个问题就变成了 如果我在前i-1行取了j次得到x的破坏值 那么我要再第i行取k次得到get[k]的破坏值 也就是前i行共取了k+j次得到了x+get[k]的破坏值 背包问题 暴力求解出每行取k个最大的破坏值即可(一个滑

Codeforces 148E Porcelain (预处理+多重背包)

E. Porcelain time limit per test:3 seconds memory limit per test:256 megabytes During her tantrums the princess usually smashes some collectable porcelain. Every furious shriek is accompanied with one item smashed. The collection of porcelain is arra

Codeforces 148E. Porcelain【多重背包】

题目大意: 有一个公主一生气就喜欢摔东西.现在有很多个柜子,每个柜子里面装着很多物品,公主每次摔东西只能随机的选择一个柜子,拿出最左边或者最右边的一个物品摔碎,给出公主最多生气的次数,求生完气之后,公主摔掉物品的价值的最大总和. 做法: 对于每个柜子来说,从左边拿和从右边拿是不一样的,假设最佳方案中,在第i个柜子中需要拿Ki个物品,那么拿着Ki个物品的最大价值我们是可以确定的.一:全从左边拿,二:全从右边拿,三,左边那一部分,右边拿一部分.最后,我们可以算出w[i][k](在第i个柜子中拿k个物

codeforces 148E Porcelain

E. Porcelain During her tantrums the princess usually smashes some collectable porcelain. Every furious shriek is accompanied with one item smashed. The collection of porcelain is arranged neatly on n shelves. Within each shelf the items are placed i

Codeforces 474D Flowers dp(水

题目链接:点击打开链接 思路: 给定T k表示T组测试数据 每组case [l,r] 有2种物品a b,b物品必须k个连续出现 问摆成一排后物品长度在[l,r]之间的方法数 思路: dp[i] = dp[i-1]+dp[i-k]; #include <iostream> #include <cmath> #include <algorithm> #include <cstdio> #include <cstring> #include <v

codeforces 148E Aragorn&#39;s Story 背包DP

Aragorn's Story Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/problem/148/E Description Our protagonist is the handsome human prince Aragorn comes from The Lord of the Rings. One day Aragorn finds a lot of enemies who

Codeforces 235B Let&#39;s Play Osu! 概率dp(水

题目链接:点击打开链接 给定n表示有n个格子 下面每个格子为O的概率是多少. 对于一段连续 x 个O的价值就是 x*x ; 问: 获得的价值的期望是多少. 思路: 把公式拆一下.. #include <cstdio> const int N = 100005; double dp[N][2], p[N]; int main(){ int n; scanf("%d", &n); for(int i = 1; i <= n; i ++) { scanf("

01背包水题篇之 HDU2955——Robberies

原来是想dp[i],表示不被抓概率为i所能抢到的最大钱(概率1-100) 后来看了别人的博客是dp[i]表示抢了i钱最大的不被抓概率,嗯~,弱菜水题都刷不动. 那么状态转移方程就是 dp[i]=max(dp[i],dp[i-money]*p),初始化dp(0~maxn)为0,dp[0]=1(1毛钱都没抢你抓个毛线啊,哥是良民~) 又是贴代码环节~ <span style="font-size:18px;">#include<iostream> #include&

01背包水题篇之HDU3466——Proud Merchants

这是个好题,菜鸟刚学dp,这题把我以前的想法全都给完完全全的颠覆了.其实是自己没了解无后效性的概念. 然后我去开开心心滴跑去问队长:"队长,队长,怎么理解动归的无后效性啊???" 学长很深沉滴对我说:"做多了就会了" "噢噢"(好吧) 然后学长又补了句:"能构成有向无环图的都能用DP搞." 我心里想:"队长就知道搞妹~~~." 默默去翻小白书看看DAG去了. 为了搞清楚这题怎么写,操了度娘千百遍,还是没搞定