1、摆花
一共有n个品种的话,给定个数一共摆m个,问一共多少种摆法。
dp[i][j]表示摆第i个品种后一共摆j个需要多少种
#include<bits/stdc++.h>
using namespace std;
const int maxn=105, mod = 1000007;
int n, m, a[maxn], dp[maxn][maxn];
int main()
{
cin>>n>>m;
for(int i=1; i<=n; i++) cin>>a[i];
dp[0][0] = 1;
for(int i=1; i<=n; i++)
for(int j=0; j<=m; j++)
for(int k=0; k<=min(j, a[i]); k++)
dp[i][j] = (dp[i][j] + dp[i-1][j-k])%mod;
cout<<dp[n][m]<<endl;//第i种需要几个
return 0;
}
当我们到第i-1时候,我们第i中的个数可以从1到min(arr[i],j)个;
2、传球游戏
n个人围成一个圈,m次传球,m次后回到原点。一共多少种。
每一次可以分别向左传还是向右传,那么就可以构造方程了。
dp[i][j]表示第i次传球到达第j个位置的次数。
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception {
Scanner cin = new Scanner(System.in);
int n=cin.nextInt(),m=cin.nextInt();
int dp[][]=new int [32][32];
dp[0][0]=1;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
{dp[i+1][(j-1+n)%n]+=dp[i][j];
dp[i+1][(j+1)%n]+=dp[i][j];}
System.out.println(dp[m][0]);
}
}
3、最大子段和
这个就是普通的最大字段和
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
const int INF=0x3f3f3f3f;
int arr[200009],f[200009],g[200009]; int n;
int main()
{
int sum=0;
cin>>n;
for(int i=1;i<=n;i++)
cin>>arr[i];
for(int i=1;i<=n;i++)
f[i]=max(f[i-1],0)+arr[i];
for(int i=1;i<=n;i++)
f[i]=max(f[i-1],f[i]);
cout<<f[n];
}
4、环状双最大子段和
一个环求两条没重叠的最大子段和
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
const int INF=0x3f3f3f3f;
int arr[200009],f[200009],g[200009]; int n;
int test()
{
int hhh=-INF;
for(int i=1;i<=n;i++) f[i]=max(f[i-1],0)+arr[i];
for(int i=n;i>=1;i--) g[i]=max(g[i+1],0)+arr[i];
for(int i=1;i<=n;i++) f[i]=max(f[i-1],f[i]);
for(int i=n;i>=1;i--) g[i]=max(g[i+1],g[i]);
for(int i=1;i<n;i++) hhh=max(hhh,f[i]+g[i+1]);
return hhh;
}
int main()
{
int sum=0;
memset(f,-0x3f,sizeof f);memset(g,-0x3f,sizeof g);
cin>>n;
for(int i=1;i<=n;i++)
{cin>>arr[i];sum+=arr[i];}
int ans=test();
for(int i=1;i<=n;i++)
arr[i]=-arr[i];
int ans1=sum+test();
if(ans1==0)ans1=-INF;
cout<<max(ans,ans1);
}
5、合唱队形
从n个人挑出若干个来,最后达到 一个模式
就是正反找最大最长序列最后在拼起来
for(int i=n-1;i>=1;i--)
for(int j=i+1;j<=n;j++)
if(arr[i]>arr[j]&&g[i]<=g[j]+1)
g[i]=g[j]+1;
最长递增序列
#include <bits/stdc++.h>
#include<iostream>
using namespace std;
int arr[110],f[110],g[110];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{cin>>arr[i];f[i]=g[i]=1;}
for(int i=2;i<=n;i++)
for(int j=1;j<i;j++)
if(arr[i]>arr[j]&&f[i]<=f[j]+1)
f[i]=f[j]+1;
for(int i=n-1;i>=1;i--)
for(int j=i+1;j<=n;j++)
if(arr[i]>arr[j]&&g[i]<=g[j]+1)
g[i]=g[j]+1;
int m=0;
for(int i=1;i<=n;i++)
{
int hh=g[i]+f[i]-1;
m=max(m,hh);
}
cout<<n-m;
}