您的位置:首页 > 其它

[NOI2005]瑰丽华尔兹 && dp单调队列

2014-12-06 16:40 525 查看
裸DP (知道要用单调队列的前提下)按照时间区间做DP 单调队列也没什么特别的 就是手写双端队列要注意清0 以及各种数组加减号有点容易打错略坑

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAXN 200
char Map[MAXN+10][MAXN+10];
int dp[MAXN+10][MAXN+10][MAXN+10];
int n, m, K;
struct node{
	int st, ed, dir;
}A[MAXN+10];
int Q[MAXN*10+10];
int F, R;
int main()
{
	int stx, sty;
	scanf("%d%d%d%d%d", &n, &m, &stx, &sty, &K);
	for(int i = 1; i <= n; i++) scanf("%s", Map[i]+1);
	memset(dp, ~0x3f, sizeof(dp));
	dp[0][stx][sty] = 0;
	for(int i = 1; i <= K; i++) scanf("%d%d%d", &A[i].st, &A[i].ed, &A[i].dir);
	
	for(int d = 1; d <= K; d++)
	{
		int T = A[d].ed - A[d].st + 1, dir = A[d].dir;
		
		for(int i = 1; i <= n; i++)
			for(int j = 1; j <= m; j++)
				dp[d][i][j] = dp[d-1][i][j];

		if(dir == 1)
			for(int j = 1; j <= m; j++)
			{
				F = R = Q[0] = 0;
				memset(Q, 0, sizeof(Q));
				for(int i = n; i >= 1; i--)
				{
					if(Map[i][j] == 'x') { F = R = Q[0] = 0; continue; }
					while(F < R && Q[F] - i > T) F++;
					dp[d][i][j] = max(dp[d][i][j], dp[d-1][Q[F]][j] + Q[F] - i);
					while(F < R && dp[d-1][i][j] + i >= dp[d-1][Q[R-1]][j] + Q[R-1]) R--;
					Q[R++] = i;
				}
			}
		
		if(dir == 2)
			for(int j = 1; j <= m; j++)
			{
				F = R = Q[0] = 0;
				memset(Q, 0, sizeof(Q));
				for(int i = 1; i <= n; i++)
				{
					if(Map[i][j] == 'x') { F = R = Q[0] = 0; continue; }
					while(F < R && i - Q[F] > T) F++;
					dp[d][i][j] = max(dp[d][i][j], dp[d-1][Q[F]][j] + i - Q[F]);
					while(F < R && dp[d-1][i][j] - i >= dp[d-1][Q[R-1]][j] - Q[R-1]) R--;
					Q[R++] = i;
				}
			}
		
		if(dir == 3)
			for(int i = 1; i <= n; i++)
			{
				F = R = Q[0] = 0;
				memset(Q, 0, sizeof(Q));
				for(int j = m; j >= 1; j--)
				{
					if(Map[i][j] == 'x') { F = R = Q[0] = 0; continue; }
					while(F < R && Q[F] - j > T) F++;
					dp[d][i][j] = max(dp[d][i][j], dp[d-1][i][Q[F]] + Q[F] - j);
					while(F < R && dp[d-1][i][j] + j >= dp[d-1][i][Q[R-1]] + Q[R-1]) R--;
					Q[R++] = j;
				}
			}
		
		if(dir == 4)
			for(int i = 1; i <= n; i++)
			{
				F = R = Q[0] = 0;
				for(int j = 1; j <= m; j++)
				{
					if(Map[i][j] == 'x') { F = R = Q[0] = 0; continue; }
					while(F < R && j - Q[F] > T) F++;
					dp[d][i][j] = max(dp[d][i][j], dp[d-1][i][Q[F]] - Q[F] + j);
					while(F < R && dp[d-1][i][j] - j >= dp[d-1][i][Q[R-1]] - Q[R-1]) R--;
					Q[R++] = j;
				}
			}
	}
	int Ans = -1;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            Ans = max(Ans, dp[K][i][j]);
    printf("%d", Ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: