1.锯齿队形
#include<algorithm>
#include<iostream>
#include<fstream>
#include<cstdio>
#define Max 30005
using namespace std;
int h[Max],f[Max],g[Max];
//f(i)代表前i个元素最后为升序的抖动序列的最大长度
//g(i)代表前i个元素最后为降序的抖动序列的最大长度
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&h[i]);
}
f[1]=1;g[1]=1;
for(int i=2;i<=n;i++){
if(h[i]==h[i-1]){
f[i]=f[i-1];
g[i]=g[i-1];
}
if(h[i]>h[i-1]){
f[i]=max(f[i-1],g[i-1]+1);
g[i]=g[i-1];
}
if(h[i]<h[i-1]){
f[i]=f[i-1];
g[i]=max(f[i-1]+1,g[i-1]);
}
}
printf("%d",n-max(f[n],g[n]));
return 0;
}
2.花匠
//话说这道题就交P1的代码都能过呢…
#include<algorithm>
#include<iostream>
#include<fstream>
#include<cstdio>
#define Max 100005
using namespace std;
int h[Max],f,g;
//f代表前i个元素最后为升序的抖动序列的最大长度
//g代表前i个元素最后为降序的抖动序列的最大长度
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&h[i]);
}
f=1;g=1;
for(int i=2;i<=n;i++){
if(h[i]>h[i-1]){
f=max(f,g+1);
}
else if(h[i]<h[i-1]){
g=max(f+1,g);
}
}
printf("%d",max(f,g));
return 0;
}
3.乘积最大
#include<algorithm>
#include<iostream>
#include<fstream>
#include<cstdio>
using namespace std;
char cha[15];
int num[15],t[15][10]={0},f[15][15]={0};
int main(){
int N,K;
scanf("%d%d",&N,&K);K++;
scanf("%s",cha+1);
for(int i=1;i<=N;i++){
num[i]=cha[i]-'0';
}
for(int i=1;i<=N;i++){
for(int j=i;j<=N;j++){
t[i][j]=t[i][j-1]*10+num[j];
}
}//t[i][j]:在num数组中,由下标i-j组成的整数
for(int i=1;i<=N;i++){
f[i][1]=t[1][i];
}//初始化分一组的情况
//函数原型:
//f[n][k]:把n个数分成k组的情况中,乘积最大的值
for(int k=2;k<=K;k++){//k=2:分一组已经考虑了
for(int n=k;n<=N;n++){//n=k:要分k组,至少要有k个元素
for(int i=k-1;i<n;i++){
//i=k-1:前i个的元素分k-1组
f[n][k]=max(f[i][k-1]*t[i+1][n],f[n][k]);
}
}
}
printf("%d",f[N][K]);
return 0;
}
4.渡河问题
公无渡河,公竟渡河。渡河而死,其奈公何?突然想到 |ू・ω・` )
#include<algorithm>
#include<iostream>
#include<fstream>
#include<cstdio>
using namespace std;
int t[2505]={0},f[2505];//带n头牛去所需要的时间
int main(){
int n,m;
scanf("%d%d",&n,&m);
int s=m;
for(int i=1;i<=n;i++){
int a;
scanf("%d",&a);
s+=a;t[i]=s;
}
f[1]=t[1]+m;
for(int i=2;i<=n;i++){
f[i]=t[i]+m;
for(int j=1;j<=i-1;j++){
if(f[i]>f[i-j]+t[j]+m){
f[i]=f[i-j]+t[j]+m;
//分成两部分:f[n-1],t[1] || f[n-2],t[2]……
}
}
}
printf("%d\n",f[n]-m);
return 0;
}
/*f[i]=min(f[i-j]+t[j]+m) {1<=i<=n,1<=j<=i-1}
f[i]=t[i]+m(初始化)*/
###5.马棚问题
//当年第一次学DP时这道题可是一坨阴影…
#include<algorithm>
#include<iostream>
#include<fstream>
#include<cstdio>
#define OO 999999999
using namespace std;
int black[505],f[505][505];
//black[i]:第1-i匹马中黑马数
//f[n][k]:将n匹马放入k个马厩里的系数总和的最小值
int main(){
int N,K;
scanf("%d%d",&N,&K);
for(int i=1;i<=N;i++){
int color;
scanf("%d",&color);
black[i]=black[i-1]+color;
f[i][1]=black[i]*(i-black[i]);//边界:i匹马分一组
}
for(int dk=2;dk<=K;dk++){
for(int dn=dk;dn<=N;dn++){
f[dn][dk]=OO;//求最小值,初始赋极大值
for(int i=dk-1;i<=dn-1;i++){
int B_horse=black[dn]-black[i];
f[dn][dk]=min(f[dn][dk],f[i][dk-1]+B_horse*((dn-i)-B_horse));
//min(前i个元素分成k-1组的不愉快系数)+第k组的不愉快系数
}
}
}
printf("%d",f[N][K]);
return 0;
}
6.数字游戏
#include<algorithm>
#include<iostream>
#include<fstream>
#include<cstdio>
#define MAXN 1000000000
using namespace std;
int N,M,ansmax=-MAXN,ansmin=MAXN;
int num[55],prefix[55]={0};
int f_min[55][15]={0},f_max[55][15]={0};
void prefix_sum(){
for(int i=1;i<=N;i++){
prefix[i]=prefix[i-1]+num[i];
}
}//用前缀和的思想,算出分一组时的和
void roll(){
for(int i=1;i<=N;i++){
num[i-1]=num[i];
}
num[N]=num[0];
}
int main(){
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++){
scanf("%d",&num[i]);
}
for(int cnt=1;cnt<=N;cnt++){//N种排序方式都要算
prefix_sum();
for(int i=1;i<=N;i++){
f_min[i][1]=(prefix[i]%10+10)%10;
f_max[i][1]=(prefix[i]%10+10)%10;
}//初始化分一组的情况
//f[n][m]:n个元素分成m组,和的最小/大值(n>=m)
for(int m=2;m<=M;m++){
for(int n=m;n<=N;n++){
f_min[n][m]=MAXN;
f_max[n][m]=-MAXN;
for(int i=m-1;i<=n-1;i++){
f_min[n][m]=min(f_min[n][m],f_min[i][m-1]*(((prefix[n]-prefix[i])%10+10)%10));
f_max[n][m]=max(f_max[n][m],f_max[i][m-1]*(((prefix[n]-prefix[i])%10+10)%10));
}
}
}
ansmax=max(ansmax,f_max[N][M]);
ansmin=min(ansmin,f_min[N][M]);
//多组ans,求最值
roll();//环状数组,每算出一次答案都要向前滚动一位
}
printf("%d\n%d",ansmin,ansmax);
return 0;
}
7.能量项链
//注意这道题以0开始计数比较方便,不用在意取模的问题
#include<algorithm>
#include<iostream>
#include<fstream>
#include<cstring>
#include<cstdio>
#define MAX 105
using namespace std;
int a[MAX],f[MAX][MAX]={0};
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
int ans=0;
memset(f,0,sizeof(f));
for(int d=1;d<n;d++){
for(int i=0;i<n;i++){
int j=(i+d)%n;//枚举距离为d的i~j的区间,用取模构成滚动数组
for(int k=i;k!=j;k=(k+1)%n){//k为项链的断点,构成不同顺序
f[i][j]=max(f[i][j],(f[i][k]+f[(k+1)%n][j])+a[i]*a[(k+1)%n]*a[(j+1)%n]);
//状转方程:(k之前裂变的能量+k之后的+本次裂变能量)与0取最大值;
}
}
}
for(int i=0;i<n;i++) ans=max(f[i][(i-1+n)%n],ans);
printf("%d",ans);
return 0;
}