动态规划要点
阶段的2个方向:从上到下;从下到上。
动态规划要点
从递归到DP
动态规划要点
两个2个方向
优化的可能性
第1题 合唱队形
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T1 < …Ti+1 > … > TK(1 <= i <= K)。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入格式
第一行是一个整数N(2 <= N <= 100),表示同学的总数。
第二行有n个整数,用空格分隔,第i个整数Ti(130 <= Ti <= 230)是第i位同学的身高(厘米)。
输出格式
包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
输入/输出例子1
输入:
8
186 186 150 200 160 130 197 220
输出:
4
样例解释
无
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define MAX 102
int high[MAX];
int left[MAX];
int right[MAX];
int main(int argc, char const *argv[])
{
int n;
while(scanf("%d",&n) != EOF) {
for(int i = 0; i < n; i++) {
scanf("%d",&high[i]);
left[i] = 0;
right[i] = 0;
}
for(int i = 0; i < n; i++) {
int max = -1;
bool isMin = true;
for(int j = i -1; j >= 0; j--) {
if(high[j] < high[i] && max < left[j]) {
max = left[j];
isMin = false;
}
}
if(!isMin) {
left[i] = max + 1;
}
}
for(int i = n-1; i >= 0; i--) {
int max = -1;
bool isMin = true;
for(int j = i + 1; j < n; j++) {
if(high[j] < high[i] && max < right[j]) {
max = right[j];
isMin = false;
}
}
if(!isMin) {
right[i] = max + 1;
}
}
int ans = n;
for(int i = 0; i < n; i++) {
int temp = n - (left[i] + right[i] + 1);
if(ans > temp) {
ans = temp;
}
}
printf("%d\n", ans);
}
return 0;
}
动态规划要点
枚举中间的方法
换一种思路:预处理
数学一例:钱币问题
A:用6个钱币,面额分别是1,2,5,10,2,5。能构成哪些付款额?
60个钱币的情况呢?
(从递归到DP----子问题与去重复运算)