题解:P2072 宗教问题

题解:P2072 宗教问题

算法分析

本题作为 dp 水题,两个回答都能 dp 解决。原理别的 dalao 讲得十分清楚。

但本题的第一回答可以考虑贪心

贪心分析

只记录集体总数,可以考虑用 set。

dp 考虑时,每个人可以加入前一个集体或新开一组。

进一步想,当前一组未满时,加入是最优的,不可能新开一组。故贪心成立。

贪心代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf=1e18;
const int N=1e3+5;
int n,m,k;
int a[N];
int min_num;
int dp_ms[N];
int num;
set<int> s;
signed main(){
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	for(int i=1;i<=n;i++){
		s.insert(a[i]);
		if(s.size()>k){
			min_num++;
			s.clear();
			s.insert(a[i]);
		}
	}
	if(s.size()>0)	min_num++;
	cout<<min_num<<endl;
	dp_ms[1]=1;
	for(int i=2;i<=n;i++){
		dp_ms[i]=inf;
		s.clear();
		num=0;
		for(int j=i;j>=1;j--){
			if(s.find(a[j])==s.end()){
				num++;
				s.insert(a[j]);
			}
			if(num>k)	break;
			dp_ms[i]=min(dp_ms[i],dp_ms[j-1]+num);
		}
	}
	cout<<dp_ms[n];
	return 0;
}

dp 代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf=1e18;
const int N=1e3+5;
int n,m,k;
int a[N];
int dp_mn[N];
int dp_ms[N];
int num;
set<int> s;
signed main(){
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	dp_mn[1]=1;
	dp_ms[1]=1;
	for(int i=2;i<=n;i++){
		dp_mn[i]=inf;
		dp_ms[i]=inf;
		s.clear();
		num=0;
		for(int j=i;j>=1;j--){
			if(s.find(a[j])==s.end()){
				num++;
				s.insert(a[j]);
			}
			if(num>k)	break;
			dp_mn[i]=min(dp_mn[i],dp_mn[j-1]+1);
			dp_ms[i]=min(dp_ms[i],dp_ms[j-1]+num);
		}
	}
	cout<<dp_mn[n]<<endl;
	cout<<dp_ms[n];
	return 0;
}

总结

第一回答,贪心 \(O(n \log n)\),dp \(O(n^2)\)

第二回答,皆为 \(O(n^2)\)

完结撒花

posted @ 2026-01-29 21:34  concert_b  阅读(0)  评论(0)    收藏  举报