记录编号 323410 评测结果 AAAAAAAAAA
题目名称 [NOI 2005]瑰丽华尔兹 最终得分 100
用户昵称 Gravatar派特三石 是否通过 通过
代码语言 C++ 运行时间 0.345 s
提交时间 2016-10-16 17:13:43 内存使用 0.48 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#define pa 	system("pause")
const int maxn=210;
using namespace std;
char g[maxn][maxn];int n,m,ax,ay,p,f[2][maxn][maxn],ans=0,dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1},deq[maxn],pos[maxn];bool tt=0;
void work(int x,int y,int edge,int type,int l)//坐标,边界,第几次倾斜,操作种类,区间长度 
{
	int s=1,e=0;//队列起点,终点 
	for(int i=1;i<=edge;++i)
	{
		if(g[x][y]=='.')
		{
			int v=f[!tt][x][y]-i;//类似单调队列优化多重背包,拉到同一水平再比较 
			while(s<=e&&deq[e]<v)--e;
			deq[++e]=v;pos[e]=i;
			while(i-pos[s]>l)++s;//失效 
			f[tt][x][y]=deq[s]+i;
		}
		else
		{
			s=1,e=0;//清空队列 
			f[tt][x][y]=-0x7f7f7f7f;//家具,无法到达 
		}
		x+=dx[type],y+=dy[type];
	}
}
int Main()
{
	freopen("adv1900.in","r",stdin);
	freopen("adv1900.out","w",stdout);
    scanf("%d%d%d%d%d",&n,&m,&ax,&ay,&p);
    for(int i=1;i<=n;++i)scanf("%s",g[i]+1);
   for(int i=1;i<=n;++i)
   		for(int j=1;j<=m;++j)f[0][i][j]=-0x7f7f7f7f;   //无法确定每次的转移,每次枚举所有位置,为了确定由起点出发,所以起点与其他点初始值必须相差较大 
	f[0][ax][ay]=0;
	tt=0;
    for(int i=1;i<=p;++i)
    {
		int s,t,d;
        scanf("%d%d%d",&s,&t,&d);
        tt=!tt;
        if(d==1)for(int j=1;j<=m;++j)work(n,j,n,1,t-s+1);
        if(d==2)for(int j=1;j<=m;++j)work(1,j,n,2,t-s+1);
        if(d==3)for(int j=1;j<=n;++j)work(j,m,m,3,t-s+1);
        if(d==4)for(int j=1;j<=n;++j)work(j,1,m,4,t-s+1);
    } 
    for(int i=1;i<=n;++i)
    	for(int j=1;j<=m;++j)ans=max(ans,f[tt][i][j]);
    printf("%d\n",ans);
} 
int start=Main();
int main(){;}