题目链接宗教问题 - 洛谷
单调队列优化多重背包(全网最详细解析)_秦三马和他的CF生涯的博客-CSDN博客
对于第一问,完全可以用贪心来写,能凑一组就凑,否则另开一组,细节的话就是i==n的时候,无论此时什么情况,都必须+1
对于第二问,采用动态规划,对于一个位置pos,它由它之前的状态推来,它和它之前危险值的和要看它往前能推几个元素,
也就是从这个pos往前开一组,每开一组就刷新dp[pos]=min(dp[pos],dp[j-1]+cnt) ,如果推的时候种类数达k+1的时候就立刻终止循环即可
#include<iostream>
#include<set>
# include<algorithm>
# include<cstring>
using namespace std;
typedef long long int ll;
int book[100];
int dp[1010];
int a[1010];
int main()
{
int n,m,k;
cin>>n>>m>>k;
fill(dp,dp+1010,99999);
int cnt=0,ans=0;
for(int i=1; i<=n; i++)
{
int x;
cin>>x;
a[i]=x;
if(book[x]==0)
{
book[x]++;
cnt++;
}
if(cnt>k)
{
memset(book,0,sizeof(book));
book[x]=1;
cnt=1;
ans++;
}
if(i==n)
ans++;
}
cout<<ans<<endl;
memset(book,0,sizeof(book));
dp[0]=0;
dp[1]=1;
for(int i=1; i<=n; i++)
{
int cnt=0;
memset(book,0,sizeof(book));
for(int j=i; j>=1; j--)
{
if(!book[a[j]])
{
cnt++;
book[a[j]]++;
}
if(cnt>k)
break;
dp[i]=min(dp[i],dp[j-1]+cnt);
}
}
cout<<dp[n];
return 0;
}