瑰麗華爾茲

瑰麗華爾茲 
你跳過華爾茲嗎?當音樂響起,當你隨着旋律滑動舞步,是不是有一種漫步仙境的愜意?衆所周知,跳華爾茲時,最重要的是有好的音樂。但是很少有幾個人知道,世界上最偉大的鋼琴家一生都漂泊在大海上,他的名字叫丹尼•佈德曼•T.D.•檸檬•1900,朋友們都叫他1900。 1900在20世紀的第一年出生在往返於歐美的郵輪弗吉尼亞號上,很不幸他剛出生就被拋棄了,成了孤兒。1900孤獨的成長在弗吉尼亞號上,從未離開過這個搖晃的世界。也許是對他命運的補償,上帝派可愛的小天使艾米麗照顧他。可能是天使的點化,1900擁有不可思議的鋼琴天賦:從未有人教,從沒看過樂譜,但他卻能憑着自己的感覺彈出最沁人心脾的旋律。當1900的音樂獲得郵輪上所有人的歡迎時,他才8歲,而此時的他已經乘着海輪往返歐美大陸50餘次了。雖說是鋼琴奇才,但1900還是個孩子,他有着和一般男孩一樣的好奇和調皮,只不過更多一層浪漫的色彩罷了:這是一個風雨交加的夜晚,海風捲起層層巨浪拍打着弗吉尼亞號,郵輪隨着巨浪劇烈的搖擺。船上的新薩克斯手馬克斯•託尼暈船了,1900招呼託尼和他一起坐上舞廳裏的鋼琴,然後鬆開了固定鋼琴的閘,於是,鋼琴隨着海輪的傾斜滑動起來。準確的說,我們的主角1900、鋼琴、郵輪隨着1900的旋律一起跳起了華爾茲,隨着“嘣嚓嚓”的節奏,託尼的暈船症也奇蹟般的消失了。後來託尼在回憶錄上寫道:大海搖晃着我們使我們轉來轉去快速的掠過燈和傢俱我意識到我們正在和大海一起跳舞真是完美而瘋狂的舞者晚上在金色的地板上快樂的跳着華爾茲是不是很愜意呢?也許,我們忘記了一個人,那就是艾米麗,她可沒閒着:她必須在適當的時候施展魔法幫助1900,不讓鋼琴碰上舞廳裏的傢俱。不妨認爲舞廳是一個N行M列的矩陣,矩陣中的某些方格上堆放了一些傢俱,其他的則是空地。鋼琴可以在空地上滑動,但不能撞上傢俱或滑出舞廳,否則會損壞鋼琴和傢俱,引來難纏的船長。每個時刻,鋼琴都會隨着船體傾斜的方向向相鄰的方格滑動一格,相鄰的方格可以是向東、向西、向南或向北的。而艾米麗可以選擇施魔法或不施魔法:如果不施魔法,則鋼琴會滑動;如果施魔法,則鋼琴會原地不動。艾米麗是個天使,她知道每段時間的船體的傾斜情況。她想使鋼琴在舞廳裏滑行路程儘量長,這樣1900會非常高興,同時也有利於治療託尼的暈船。但艾米麗還太小,不會算,所以希望你能幫助她。


Input
輸入文件的第一行包含5個數N, M, x, y和K。N和M描述舞廳的大小,x和y爲鋼琴的初始位置(x行y列);我們對船體傾斜情況是按時間的區間來描述的,且從1開始計量時間,比如“在[1, 3]時間裏向東傾斜,[4, 5]時間裏向北傾斜”,因此這裏的K表示區間的數目。以下N行,每行M個字符,描述舞廳裏的傢俱。第i行第j列的字符若爲‘ . ’,則表示該位置是空地;若爲‘ x ’,則表示有傢俱。以下K行,順序描述K個時間區間,格式爲:si ti di。表示在時間區間[si, ti]內,船體都是向di方向傾斜的。di爲1, 2, 3, 4中的一個,依次表示北、南、西、東(分別對應矩陣中的上、下、左、右)。輸入保證區間是連續的,即 s1 = 1 si = ti-1 + 1 (1 < i ≤ K) tK = T


Output
輸出文件僅有1行,包含一個整數,表示鋼琴滑行的最長距離(即格子數)。


Sample Input
4 5 4 1 3
..xx.
.....
...x.
.....
1 3 4
4 5 1
6 7 3
Sample Output
6
dp[i][x][y]:表示第i次滑動在(x,y)處最大路程。
向北:dp[i][x][y]=max(dp[i-1][x-k][y]+k)
向南:dp[i][x][y]=max(dp[i-1][x+k][y]+k)
向東:dp[i][x][y]=max(dp[i-1][x][y-k]+k)
向西:dp[i][x][y]=max(dp[i-1][x][y+k]+k)

觀察可省掉i這一維,然後單調隊列維護最佳的k值

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<queue>
#include<vector>
#include<cmath>
#include<cstring>
#include<deque>
using namespace std;
const int N=2000+10;
struct node{
	int num,pos;
	node(){}
	node(int a,int b){
		num=a,pos=b;
	}
};
deque <node> q;
int n,m,x,y,k,s,t,d,len,ans;
int dp[N][N],dd[5][2]={{0,0},{-1,0},{1,0},{0,-1},{0,1}};
char str[N][N];
bool inarea(int x,int y){
	return x>=1&&x<=n&&y>=1&&y<=m;
}
void DP(int x,int y,int d,int len){
	q.clear();
	for(int i=0;inarea(x,y);i++,x+=dd[d][0],y+=dd[d][1]){
		if(str[x][y]=='x')	{q.clear();continue ;}
		while(!q.empty()&&q.back().num+i-q.back().pos<=dp[x][y])
			q.pop_back();
		q.push_back(node(dp[x][y],i));
		while(!q.empty()&&(i-q.front().pos)>len)
			q.pop_front();
		dp[x][y]=q.front().num+i-q.front().pos;
		ans=max(ans,dp[x][y]);
	}
}
int main(){
    while(~scanf("%d%d%d%d%d",&n,&m,&x,&y,&k)){
		for(int i=1;i<=n;i++)
			scanf("%s",str[i]+1);
		memset(dp,0x8f,sizeof(dp));
		dp[x][y]=ans=0;
		for(int i=1;i<=k;i++){
			scanf("%d%d%d",&s,&t,&d),len=t-s+1;
			if(d<=2)for(int j=1;j<=m;j++)
				DP(d==1?n:1,j,d,len);
			else	for(int j=1;j<=n;j++)
				DP(j,d==3?m:1,d,len);
		}
		printf("%d\n",ans);
	}
}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章