题目链接:http://codeforces.com/problemset/problem/148/E

E. Porcelain
time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

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 in one row, so that one can access
only the outermost items — the leftmost or the rightmost item, not the ones in the middle of the shelf. Once an item is taken, the next item on that side of the shelf can be accessed (see example). Once an item is taken, it can't be returned to the shelves.

You are given the values of all items. Your task is to find the maximal damage the princess' tantrum of m shrieks can inflict on the
collection of porcelain.

Input

The first line of input data contains two integers n (1 ≤ n ≤ 100)
and m (1 ≤ m ≤ 10000).
The next n lines contain the values of the items on the shelves: the first number gives the number of items on this shelf (an integer
between 1 and 100, inclusive),
followed by the values of the items (integers between 1 and 100,
inclusive), in the order in which they appear on the shelf (the first number corresponds to the leftmost item, the last one — to the rightmost one). The total number of items is guaranteed to be at least m.

Output

Output the maximal total value of a tantrum of m shrieks.

Examples
input
2 3
3 3 7 2
3 4 1 5
output
15
input
1 3
4 4 3 1 2
output
9
Note

In the first case there are two shelves, each with three items. To maximize the total value of the items chosen, one can take two items from the left side of the first shelf and one item from the right side of the second shelf.

In the second case there is only one shelf, so all three items are taken from it — two from the left side and one from the right side.


题解:

方法一:

1.对于每个书架,求出每种长度下的首尾相连的最大连续和。

2.通过类似解决背包问题的方法,求得在这些最大连续和的组合下的最大值,即为答案。

方法二:

反向思维:求两边的和最大,即求中间的和最小。

1.对于每个书架,求出每种长度下的最小连续和。

2.通过类似解决背包问题的方法,求得在这些最小连续和的组合下的最小值,然后再用总和减去这个最小值,即为答案。

写法:

i为第i个书架, j为dp到当前待组合的个数, k则为对于每一个书架相应的连续个数。

写法一:从小往大推,此时dp数组需要开二维。

写法二:从大往小推,此时dp数组只需开一维。

注意:写法二必须保证这一阶段的数据只能从上一阶段的数据转移过来, 而不能从同一阶段转移过来,否则会出现重复。

方法一写法一:

 #include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const double eps = 1e-;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int maxn = 1e4+; int n, m;
int dp[][maxn];
int a[][], sum[][], s[][]; void init()
{
scanf("%d%d",&n, &m);
for(int i = ; i<=n; i++)
{
scanf("%d",&a[i][]);
for(int j = ; j<=a[i][]; j++)
scanf("%d",&a[i][j]);
} for(int i = ; i<=n; i++) //求前缀和
for(int j = ; j<=a[i][]; j++)
sum[i][j] = sum[i][j-] + a[i][j]; for(int i = ; i<=n; i++) //求每个书架每种长度下,首尾相连序列的最大连续和
for(int l = ; l<=a[i][]; l++)
for(int r = ; l+r<=a[i][]; r++)
s[i][l+r] = max(s[i][l+r], sum[i][l] + sum[i][a[i][]] - sum[i][a[i][]-r]);
} void solve()
{
for(int i = ; i<=n; i++) //01背包的拓展,每个状态都从O(n)转移过来, 而普通背包则为O(1)
{
for(int j = ; j<=m; j++) //别忘了上一阶段的j状态也参与当前阶段j状态的转移
dp[i][j] = dp[i-][j]; for(int j = ; j<=m; j++)
for(int k = ; k<=min(j,a[i][]); k++)
dp[i][j] = max(dp[i][j], s[i][k]+dp[i-][j-k]);
}
cout<<dp[n][m]<<endl;
} int main()
{
init();
solve();
}

方法一写法二:

 #include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const double eps = 1e-;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int maxn = 1e4+; int n, m;
int dp[maxn];
int a[][], sum[][], s[][]; void init()
{
scanf("%d%d",&n, &m);
for(int i = ; i<=n; i++)
{
scanf("%d",&a[i][]);
for(int j = ; j<=a[i][]; j++)
scanf("%d",&a[i][j]);
} for(int i = ; i<=n; i++)
for(int j = ; j<=a[i][]; j++)
sum[i][j] = sum[i][j-] + a[i][j]; for(int i = ; i<=n; i++)
for(int l = ; l<=a[i][]; l++)
for(int r = ; l+r<=a[i][]; r++)
s[i][l+r] = max(s[i][l+r], sum[i][l] + sum[i][a[i][]] - sum[i][a[i][]-r]);
} void solve()
{
for(int i = ; i<=n; i++)
for(int j = m; j>=; j--)
for(int k = ; k<=min(j,a[i][]); k++)
dp[j] = max(dp[j], s[i][k]+dp[j-k]); cout<<dp[m]<<endl;
} int main()
{
init();
solve();
}

方法二写法一:

 #include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const double eps = 1e-;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int maxn = 1e4+; int n, m, all;
int dp[][maxn];
int a[][], sum[][], s[][]; void init()
{
scanf("%d%d",&n, &m);
m = -m;
for(int i = ; i<=n; i++)
{
scanf("%d",&a[i][]);
for(int j = ; j<=a[i][]; j++)
scanf("%d",&a[i][j]), all += a[i][j];
m += a[i][];
} for(int i = ; i<=n; i++) //前缀和
for(int j = ; j<=a[i][]; j++)
sum[i][j] = sum[i][j-] + a[i][j]; for(int i = ; i<=n; i++) //最小连续和,因为“最小”,所以需要初始化为最大
for(int j = ; j<=a[i][]; j++)
s[i][j] = INF; for(int i = ; i<=n; i++) //求最小连续和
for(int j = ; j<=a[i][]; j++)
for(int k = ; k<=j; k++)
s[i][j-k+] = min(s[i][j-k+], sum[i][j]-sum[i][k-]);
} void solve()
{
for(int i = ; i<=n; i++) //需要所有都初始化为最大
for(int j = ; j<=m; j++)
dp[i][j] = INF; for(int i = ; i<=n; i++)
{
for(int j = ; j<=m; j++)
dp[i][j] = dp[i-][j]; for(int j = ; j<=m; j++)
for(int k = ; k<=min(j,a[i][]); k++)
dp[i][j] = min(dp[i][j], s[i][k]+dp[i-][j-k]);
}
cout<<all - dp[n][m]<<endl;
} int main()
{
init();
solve();
}

方法二写法二:

 #include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const double eps = 1e-;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int maxn = 1e4+; int n, m, all;
int dp[maxn];
int a[][], sum[][], s[][]; void init()
{
scanf("%d%d",&n, &m);
m = -m;
for(int i = ; i<=n; i++)
{
scanf("%d",&a[i][]);
for(int j = ; j<=a[i][]; j++)
scanf("%d",&a[i][j]), all += a[i][j];
m += a[i][];
} for(int i = ; i<=n; i++)
for(int j = ; j<=a[i][]; j++)
sum[i][j] = sum[i][j-] + a[i][j]; for(int i = ; i<=n; i++)
for(int j = ; j<=a[i][]; j++)
s[i][j] = INF; for(int i = ; i<=n; i++)
for(int j = ; j<=a[i][]; j++)
for(int k = ; k<=j; k++)
s[i][j-k+] = min(s[i][j-k+], sum[i][j]-sum[i][k-]);
} void solve()
{
for(int j = ; j<=m; j++)
dp[j] = INF; for(int i = ; i<=n; i++)
for(int j = m; j>=; j--)
for(int k = ; k<=min(j,a[i][]); k++)
dp[j] = min(dp[j], s[i][k]+dp[j-k]); cout<<all-dp[m]<<endl;
} int main()
{
init();
solve();
}

Codeforces Round #105 (Div. 2) E. Porcelain —— DP(背包问题)的更多相关文章

  1. 水题 Codeforces Round #105 (Div. 2) B. Escape

    题目传送门 /* 水题:这题唯一要注意的是要用double,princess可能在一个小时之内被dragon赶上 */ #include <cstdio> #include <alg ...

  2. Codeforces Round #105 (Div. 2) D. Bag of mice 概率dp

    题目链接: http://codeforces.com/problemset/problem/148/D D. Bag of mice time limit per test2 secondsmemo ...

  3. Codeforces Round #260 (Div. 1) A - Boredom DP

    A. Boredom Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/455/problem/A ...

  4. Codeforces Round #131 (Div. 1) B. Numbers dp

    题目链接: http://codeforces.com/problemset/problem/213/B B. Numbers time limit per test 2 secondsmemory ...

  5. Codeforces Round #131 (Div. 2) B. Hometask dp

    题目链接: http://codeforces.com/problemset/problem/214/B Hometask time limit per test:2 secondsmemory li ...

  6. Codeforces Round #276 (Div. 1) D. Kindergarten dp

    D. Kindergarten Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/proble ...

  7. Codeforces Round #105 (Div. 2) ABCDE

    A. Insomnia cure 哎 只能说英语太差,一眼题我看了三分钟. 题意:给5个数k, l, m, n 和 d,求1~d中能被k, l, m, n 至少一个整除的数的个数. 题解:…… 代码: ...

  8. Codeforces Round #533 (Div. 2) C.思维dp D. 多源BFS

    题目链接:https://codeforces.com/contest/1105 C. Ayoub and Lost Array 题目大意:一个长度为n的数组,数组的元素都在[L,R]之间,并且数组全 ...

  9. Codeforces Round #539 (Div. 2) 异或 + dp

    https://codeforces.com/contest/1113/problem/C 题意 一个n个数字的数组a[],求有多少对l,r满足\(sum[l,mid]=sum[mid+1,r]\), ...

随机推荐

  1. 松鼠的新家(lca)

    洛谷—— P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的 ...

  2. DNS重绑定DNS Rebinding攻击

    DNS重绑定DNS Rebinding攻击 在网页浏览过程中,用户在地址栏中输入包含域名的网址.浏览器通过DNS服务器将域名解析为IP地址,然后向对应的IP地址请求资源,最后展现给用户.而对于域名所有 ...

  3. luogu P2056 采花

    题目描述 萧芸斓是 Z国的公主,平时的一大爱好是采花. 今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花.花园足够大,容纳了 n 朵花,花有 c 种颜色(用整数 1-c 表示) ,且花是排成 ...

  4. TdxBarButton的FASTSCRIPT封装

    TdxBarButton的FASTSCRIPT封装 // cxg 2017-2-13 unit fs_dev; interface{$i fs.inc}uses fs_iinterpreter, fs ...

  5. 获取path的几种方式:NSFileManager NSHomeDirectory NSBundle

    //---------------------------------------------------------------------------------NSFileManager *fi ...

  6. 使用Crashlytics来保存应用崩溃信息

    使用Crashlytics来保存应用崩溃信息 本文首发于InfoQ,版权归InfoQ所有,转载请保留原文链接. 简介 Crashlytic 成立于2011年,是专门为移动应用开者发提供的保存和分析应用 ...

  7. c# 时间相关

    1.求时间差,两种方式(时间是否小于1800秒) 第一种: DateTime startTime = DateTime.Now; ... DateTime.Now.Subtract(startTime ...

  8. final 和static

    一.final 1.final变量: 当你在类中定义变量时,在其前面加上final关键字,那便是说,这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引 ...

  9. 使用mark-sweep算法的垃圾回收器

    在我写C++代码的那些时间里,我没有写过垃圾回收器,也没有实现过自己的内存分配器,这方面的文章倒是看了不 少.比如我在写C#代码时只管new而不需要释放,我也明白有个垃圾回收器在那帮我回收那些堆上的对 ...

  10. Canvas学习笔记——弹动

    如果有一根橡皮筋拴住一个小球,将小球拉开一定距离后释放,小球将会弹动.距离越远,橡皮筋对小球施加的外力越大,小球的加速度就越大.也就是说,小球的加速度与距离是成正比例关系的.这和缓动很相似,缓动是速度 ...