其他分享
首页 > 其他分享> > 洛谷 P6764 [APIO2020]粉刷墙壁(dp,贪心)

洛谷 P6764 [APIO2020]粉刷墙壁(dp,贪心)

作者:互联网

传送门


解题思路

第一步,求出从每个墙壁开始刷是否合法。
第二步,合法的墙壁位置作为每个区间的左端点,变成区间覆盖问题。
第二步很显然是个贪心,重点是第一步如何解决。
我们设dp[i][j]表示从第i个墙壁第j个承包商开始刷能刷的墙壁的数量。
那么

优化:
空间上:滚动数组。
时间上:对于确定的i,枚举喜欢c[i]颜色的承包商。
交互题真的恶心,不知道怎么调试代码

AC代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=100005;
vector<int> d[maxn];
int n,m,k,vis[2][maxn],dp[2][maxn],ok[maxn];
struct node{
	int l,r;
}s[maxn];
bool cmp(node a,node b){
	return a.l<b.l;
}
int minimumInstructions(int N,int M,int K,vector<int> C,vector<int> A,vector<vector<int> > B){
	n=N;
	m=M;
	k=K;
	for(int i=1;i<=n;i++) C[i-1]++;
	for(int i=1;i<=m;i++){
		for(int j=0;j<A[i-1];j++) B[i-1][j]++;
	}
	for(int i=1;i<maxn;i++) d[i].push_back(0);
	for(int i=1;i<=m;i++){
		for(int j=0;j<A[i-1];j++) d[B[i-1][j]][0]++,d[B[i-1][j]].push_back(i);
	}
	for(int i=n;i>=1;i--){
		for(int j=1;j<=d[C[i-1]][0];j++){
			if(vis[(i+1)&1][d[C[i-1]][j]%m+1]==i+1) dp[i&1][d[C[i-1]][j]]=dp[(i+1)&1][d[C[i-1]][j]%m+1]+1;
			else dp[i&1][d[C[i-1]][j]]=1;
			vis[i&1][d[C[i-1]][j]]=i; 
			if(dp[i&1][d[C[i-1]][j]]>=m) ok[i]=1;
		}
	}
	int cnt=0;
	for(int i=1;i<=n-m+1;i++){
		if(ok[i]){
			cnt++;
			s[cnt].l=i;
			s[cnt].r=i+m-1;
		}
	}
	sort(s+1,s+cnt+1,cmp);
	int now=0,ans=0;
	for(int i=1;i<=cnt;i++){
		if(s[i].l>now+1){
			return -1;
		}
		int maxr=s[i].r;
		while(i<cnt&&s[i+1].l<=now+1){
			maxr=max(maxr,s[i+1].r);
			i++;
		}
		ans++;
		now=maxr;
	}
	if(now<n){
		return -1;
	}
	return ans;
}

标签:洛谷,int,承包商,墙壁,maxn,APIO2020,P6764,include,dp
来源: https://www.cnblogs.com/yinyuqin/p/15257596.html