[POI2013]Bajtokomputer

[POI2013]Bajtokomputer

题目大意:

给定一个长度为(n(nle10^6))的由({-1,0,1})组成的序列,你可以进行(A_i+=A_{i-1})这样的操作,问通过若干次操作能否使其变成不降序列。若果能,求最小操作次数。

思路:

显然若能通过若干次操作使其变成不降序列,则一定存在一种方案使得最后(A_iin{-1,0,1})

(f_{i,j})表示前(i)个数,最后一个数为(j),能构成不降序列的最小操作次数,分不操作、操作(1)次、操作(2)次转移即可。

时间复杂度(mathcal O(n))

源代码:

#include<cstdio>
#include<cctype>
#include<climits>
#include<algorithm>
inline int getint() {
	register char ch;
	register bool neg=false;
	while(!isdigit(ch=getchar())) neg|=ch=='-';
	register int x=ch^'0';
	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
	return neg?-x:x;
}
const int N=1e6+1;
int a[N],f[N][3];
int main() {
	const int n=getint();
	for(register int i=1;i<=n;i++) {
		a[i]=getint();
		f[i][0]=f[i][1]=f[i][2]=INT_MAX;
		for(register int j=-1;j<=1;j++) {
			if(f[i-1][j+1]==INT_MAX) continue;
			if(a[i]>=j) f[i][a[i]+1]=std::min(f[i][a[i]+1],f[i-1][j+1]);
			if(i!=1&&a[i]!=j&&a[i]+j>=j) f[i][a[i]+j+1]=std::min(f[i][a[i]+j+1],f[i-1][j+1]+1);
			if(i!=1&&a[i]+j*2>=j) {
				if(a[i]+j*2<-1||a[i]+j*2>1) continue;
				f[i][a[i]+j*2+1]=std::min(f[i][a[i]+j*2+1],f[i-1][j+1]+2);
			}
		}
	}
	int ans=INT_MAX;
	for(register int i=0;i<=2;i++) ans=std::min(ans,f[n][i]);
	if(ans==INT_MAX) {
		puts("BRAK");
		return 0;
	}
	printf("%d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/skylee03/p/9598114.html