P2254 [NOI2005]瑰丽华尔兹

\(P2254\) $ [NOI2005]$ 瑰丽华尔兹

\(f(i,x,y)\)表示\(i\)时刻在\((x,y)\)点的最长路径

1900可以固定,也可以随波逐流

\[f(i,x,y) = \max(f(i-1,x,y),f(i-1,x',y')+1) \]

时间复杂度\(O(n^2t)\)

爆炸了,只能过一半

再看数据范围,显然\(O(n^2k)\)才是正解

考虑同一时间段,停和不停可以化为一段连续的区间(就算你时停时不停,也可以把停放到一起,不停放到一起,并不影响)

也就是说如果按时间段来考虑,可以看做一直在走(这么明显的东西扯这么半天)

\(f(i,x,y)\)表示当前在第\(i\)个区间,在\((x,y)\)的最长路径

\[f(i,x,y) = \max(f(i-1,x',y')+dis(x',y',x,y)) \]

时间复杂度\(O(n^3k)\)

但区间长度是有范围的,变化的那一维就有了范围,辣么可以单调队列优化变化的那一维

时间复杂度\(O(n^2k)\),稳过

代码

const int N = 210;
int n,m,sx,sy,k,ans,f[N][N];
int dx[] = {0,-1,1,0,0},dy[] = {0,0,0,-1,1};
char a[N][N];

struct node {
	int id,f;
	node(int id = 0,int f = 0):id(id),f(f){}
}q[N];int l,r;

void calc(int x,int y,int L,int d) {
	l = 1,r = 0;
	for(int i = 1;x >= 1 && y >= 1 && x <= n && y <= m; ++i,x += dx[d],y += dy[d]) {
		if(a[x][y] == 'x') l = 1,r = 0;
		else {
			while(l <= r && q[r].f+i-q[r].id < f[x][y]) --r;
			q[++r] = node(i,f[x][y]);//入的是k-1
			while(l <= r && q[l].id < i-L) ++l;
			if(l <= r) f[x][y] = q[l].f+(i-q[l].id),ans = max(ans,f[x][y]);//求的是k 
			else f[x][y] = -0x3f3f3f3f;
		}
	}
}

int main() {
	in(n); in(m); in(sx); in(sy); in(k);
	memset(f,~0x3f,sizeof(f));
	f[sx][sy] = 0;
	for(int i = 1;i <= n; ++i) scanf("%s",a[i]+1);
	for(int i = 1,s,t,d;i <= k; ++i) {
		in(s); in(t); in(d);
		int L = t-s+1;
		if(d == 1) for(int i = 1;i <= m; ++i) calc(n,i,L,d);
		if(d == 2) for(int i = 1;i <= m; ++i) calc(1,i,L,d);
		if(d == 3) for(int i = 1;i <= n; ++i) calc(i,m,L,d);
		if(d == 4) for(int i = 1;i <= n; ++i) calc(i,1,L,d);
	}
	out(ans);
	return 0;
}
posted @ 2019-10-28 09:12  陈星卿  阅读(166)  评论(0编辑  收藏  举报