1.摆花问题

题目描述
小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆。通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号。为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时同一种花放在一起,且不同种类的花需按标号的从小到大的顺序依次摆列。
试编程计算,一共有多少种不同的摆花方案。

输入
输入共2行。
第一行包含两个正整数n和m,中间用一个空格隔开。
第二行有n个整数,每两个整数之间用一个空格隔开,依次表示a1、a2、……an。

输出
输出只有一行,一个整数,表示有多少种方案。注意:因为方案数可能很多,请输出方案数对1000007取模的结果。

样例输入
2 4
3 2
样例输出
2
提示

样例说明:

有2种摆花的方案,分别是(1,1,1,2),(1,1,2,2)。括号里的1和2表示两种花,比如第一个方案是前三个位置摆第一种花,第四个位置摆第二种花。

对于20%数据,有0<n≤8,0<m≤8,0≤ai≤8;

对于50%数据,有0<n≤20,0<m≤20,0≤ai≤20;

对于100%数据,有0<n≤100,0<m≤100,0≤ai≤100。

代码:

#include <bits/stdc++.h>
using namespace std; const int mod = ;
int N, M;
int a[];
int dp[][]; int main() {
scanf("%d%d", &N, &M);
for(int i = ; i <= N; i ++)
scanf("%d", &a[i]); // 不管放多少盆花 如果只有一种那么方案书一定是 1
for(int i = ; i <= a[]; i ++)
dp[][i] = ; for(int i = ; i <= N; i ++) {
for(int j = ; j <= M; j ++) {
for(int k = ;k <= min(a[i], j); k ++)
dp[i][j] = (dp[i][j] + dp[i - ][j - k]) % mod;
}
} printf("%d\n", dp[N][M]);
return ;
}

简单 dp  dp[i][j] 表示摆了前 i 种花一共摆了 j 盆的方案数

2.合唱队问题

描述   

N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T1<...<Ti>Ti+1>…>TK(1<=i<=K)。 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

输入格式

输入的第一行是一个整数N(2<=N<=100),表示同学的总数。第一行有n个整数,用空格分隔,第i个整数Ti(130<=Ti<=230)是第i位同学的身高(厘米)。

输出格式

输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。

样例输入

8

186 186 150 200 160 130 197 220

样例输出

4

代码:

#include <bits/stdc++.h>
using namespace std; int N;
int a[], b[];
int l[], r[]; int main() {
scanf("%d", &N);
for(int i = ; i < N; i ++) {
scanf("%d", &a[i]);
b[i] = a[i];
} for(int i = ; i <= N / ; i ++)
swap(a[i], a[N - - i]); for(int i = ; i < N; i ++) {
for(int j = ; j < i; j ++)
if(b[i] > b[j])
l[i] = max(l[i], l[j] + );
} for(int i = ; i < N; i ++) {
for(int j = ; j < i; j ++)
if(a[i] > a[j])
r[i] = max(r[i], r[j] + );
} int ans = ;
for(int i = ; i < N; i ++)
ans = max(l[i] + r[i] - , ans); printf("%d\n", N - ans);
return ;
}

正向反向求最长严格上升子序列枚举中间点 i 因为 i 被算了两次是重复的所以要减去 1

3.方格取数

题目描述

设有N×N的方格图(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。
某人从图的左上角的AA点出发,可以向下行走,也可以向右走,直到到达右下角的BB点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。
此人从(0, 0)点到(n,n)点共走两次,试找出2条这样的路径,使得取得的数之和为最大。

输入:

8
6 1 7
3 2 9
2 3 5
1 4 3
3 4 3
6 6 6
1 7 1
0 0 0

输出:
67

代码:

#include <bits/stdc++.h>
using namespace std; int N;
int mp[][];
int dp[][][][]; int main() {
scanf("%d", &N);
int x, y, z;
while(~scanf("%d%d%d", &x, &y, &z)) {
if(!x && !y && !z) break;
mp[x][y] = z;
} for(int i = ; i <= N; i ++)
for(int j = ; j <= N; j ++)
for(int k = ; k <= N; k ++)
for(int l = ; l <= N; l ++) {
dp[i][j][k][l] = max(max(dp[i - ][j][k - ][l], dp[i][j - ][k][l - ]),
max(dp[i - ][j][k][l - ],dp[i][j - ][k - ][l]))+mp[i][j]; if(i != k || j != l) dp[i][j][k][l] += mp[k][l];
} printf("%d\n", dp[N][N][N][N]);
return ;
}

两个同时走 四维 dp 时间复杂度 $O(N^4)$  还有一个时间复杂度为 $O(N^3)$  的写法

4.乘积最大

题目描述:

设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积最大。例如,数字串为312,当N=3,K=1时会有以下两种分法:3*12=36和31*2=62,符合题目要求的结果为31*2=62。程序的输入共有两行:第一行共有两个自然数N、K(6<=N<=40,1<=K<=6),第二行是一个长度为N的数字串,输出一个整数,表示求得的最大乘积。

输入格式
第 1 行为整数 n,n≤50。
第 2 行为整数 k,k≤10。
第 3 行为数字字符串。
输出格式
一行一个数,表示最大的乘积。
输入样例
6
3
310143
输出样例
3720

代码:

#include <bits/stdc++.h>
using namespace std; int N, K;
string s;
int dp[][];
int num[][]; int main() {
scanf("%d%d", &N, &K);
cin >>s; memset(dp, , sizeof(dp));
for(int i = ; i < N; i ++) {
int sum = ;
for(int j = i; j < N; j ++) {
sum = sum * + (s[j] - '');
num[i][j] = sum;
}
} for(int i = ; i < N; i ++)
dp[i][] = num[][i]; for(int i = ; i < N; i ++)
for(int j = ; j <= K; j ++)
for(int k = ; k < i; k ++)
dp[i][j] = max(dp[k][j - ] * num[k + ][i], dp[i][j]); printf("%d\n", dp[N - ][K]);
return ;
}

dp[i][j] 代表的是在 s[0] 到 s[i] 的字符串中插入 j 个乘号最大乘积 num[i][j] 代表 以 s[i] 开始以 s[j] 结尾的数字大小 状态转移方程为 $dp[i][j] = max(dp[k][j - 1] * num[k + 1][i], dp[i][j])$

5.书的抄写

Description

有M本书(编号为1,2,…,M),每本书都有一个页数(分别是P1,P2,…,PM)。想将每本都复制一份。将这M本书分给K个抄写员(1<=K<=M<=500),每本书只能分配给一个抄写员进行复制。每个抄写员至少被分配到一本书,而且被分配到的书必须是连续顺序的。复制工作是同时开始进行的,并且每个抄写员复制一页书的速度都是一样的。所以,复制完所有书稿所需时间取决于分配得到最多工作的那个抄写员的复制时间。试找一个最优分配方案,使分配给每一个抄写员的页数的最大值尽可能小。

Input

第一行两个整数M、K;(K<=M<=500) 
第二行M个整数,第i个整数表示第i本书的页数。

Output

1.输出为一个数,即分配给每一个抄写员的页数的最大值

2.共 K 行,每行 2 个正整数,第 i 行表示第 i 个人抄写的书的起始编号和终止编号,每两个数之间用一个空格隔开。K 行的起始编号应该从小到大排列,如果有多解,则尽可能让前面的人少抄写

Sample Input

9 3
1 2 3 4 5 6 7 8 9

Sample Output

1.

17

2.

1-5 (15页) 
6-7 (13页) 
8-9 (17页)

代码:

#include <bits/stdc++.h>
using namespace std; #define inf 0x3f3f3f3f
int N, K;
int p[], sum[];
int dp[][]; int main() {
scanf("%d%d", &N, &K); memset(sum, , sizeof(sum));
for(int i = ; i <= N; i ++) {
scanf("%d", &p[i]);
sum[i] = sum[i - ] + p[i];
} memset(dp, inf, sizeof(dp));
for(int i = ; i <= K; i ++) {
for(int j = i; j <= N; j ++) {
if(i == ) dp[i][j] = sum[j];
else {
for(int k = i - ; k <= j - ; k ++)
dp[i][j] = min(max(dp[i - ][k], sum[j] - sum[k]), dp[i][j]);
}
}
} printf("%d\n", dp[K][N]);
return ;
}

dp[i][j] 代表 i 个人 抄写 j 本书耗时最短 代码是输出 1 的结果 输出 2 不会 :-(

被 dp 折磨的一上午 开发智力???想豁奶茶了

简单 dp的更多相关文章

  1. HDU 1087 简单dp,求递增子序列使和最大

    Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 ...

  2. Codeforces Round #260 (Div. 1) A. Boredom (简单dp)

    题目链接:http://codeforces.com/problemset/problem/455/A 给你n个数,要是其中取一个大小为x的数,那x+1和x-1都不能取了,问你最后取完最大的和是多少. ...

  3. codeforces Gym 100500H A. Potion of Immortality 简单DP

    Problem H. ICPC QuestTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100500/a ...

  4. 简单dp --- HDU1248寒冰王座

    题目链接 这道题也是简单dp里面的一种经典类型,递推式就是dp[i] = min(dp[i-150], dp[i-200], dp[i-350]) 代码如下: #include<iostream ...

  5. poj2385 简单DP

    J - 简单dp Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:65536KB     64bit ...

  6. hdu1087 简单DP

    I - 简单dp 例题扩展 Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:32768KB     ...

  7. poj 1157 LITTLE SHOP_简单dp

    题意:给你n种花,m个盆,花盆是有顺序的,每种花只能插一个花盘i,下一种花的只能插i<j的花盘,现在给出价值,求最大价值 简单dp #include <iostream> #incl ...

  8. hdu 2471 简单DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2571 简单dp, dp[n][m] +=(  dp[n-1][m],dp[n][m-1],d[i][k ...

  9. Codeforces 41D Pawn 简单dp

    题目链接:点击打开链接 给定n*m 的矩阵 常数k 以下一个n*m的矩阵,每一个位置由 0-9的一个整数表示 问: 从最后一行開始向上走到第一行使得路径上的和 % (k+1) == 0 每一个格子仅仅 ...

  10. poj1189 简单dp

    http://poj.org/problem?id=1189 Description 有一个三角形木板,竖直立放.上面钉着n(n+1)/2颗钉子,还有(n+1)个格子(当n=5时如图1).每颗钉子和周 ...

随机推荐

  1. Velocity学习2

    Velocity是一个基于java的模板引擎(template engine).它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象. 当Veloci ...

  2. [并发并行]_[C/C++]_[C++标准库里的线程安全问题]

    场景 1.写普通的程序时, 经常会使用cout来做输出, 每个进程只有一个控制台, 如果多线程调用cout时会出状况吗? 2.之所以研究cout会不会在并发下调用有问题, 是因为曾经有一个bug的崩溃 ...

  3. MongoDB操作-备份和恢复,导入和导出

    mongodb数据备份和恢复主要分为二种:一种是针对库的mongodump和mongorestore,一种是针对库中表的mongoexport和mongoimport 1. 常用命令格式 mongod ...

  4. UVA10559 Blocks

    玄学东西,毒瘤状态,死也想不出 设f[l][r][i]表示[l,r]区间,右边再加上i个颜色和r颜色相同的块,消掉这些的最大收益 两种转移方式: 把r和后面i个一起销毁,\(f[l][r-1][0]+ ...

  5. 日常的例子说明 throttle 和 debounce 的区别

    不小心接触到 throttle 和 debounce,按捺不住猎奇的心理,找这两个函数的资料. 然而百度到的各种对他们的理解,我去啊. 艰难地搞明白他们是干嘛的之后,忍不住举个例子说说自己的理解,希望 ...

  6. 180807-Quick-Task 动态脚本支持框架之Groovy脚本加载执行

    Quick-Task 动态脚本支持框架之Groovy脚本加载执行 上一篇简答说了如何判断有任务动态添加.删除或更新,归于一点就是监听文件的变化,判断目录下的Groovy文件是否有新增删除和改变,从而判 ...

  7. 自动化运维工具saltstack05 -- 之salt-ssh模式

    salt-ssh模式 1.说明: salt-ssh即通过ssh得方式进行管理,不需要安装salt-minion, salt-ssh 用的是sshpass进行密码交互的. 2.salt-ssh得局限性 ...

  8. ats缓存规则

    一. 用户访问过程:1. ats收到一个用户对web对象的请求;2. 使用该地址, ats尝试着在其对象数据库(缓存)中用被请求对象的地址来定位该对象;3. 如果对象在缓存中, ats会检查该对象是否 ...

  9. PyCharm配置SFTP远程调试Django应用

    http://www.ithao123.cn/content-41747.html http://www.th7.cn/system/lin/201703/205998.shtml

  10. C/C++:static用法总结

    前言:static是C/C++中一个很重要的关键字,最近阅读了很多博客和资料,遂在此对自己的学习笔记进行简单的总结并发表在这里 一.C语言中的static • 静态全局变量:在全局变量之前加上关键字s ...