Bzoj 1833
Bzoj 2741

Bzoj 1499

coc youyl posted @ 2015年6月27日 21:15 in bzoj , 517 阅读

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1499

题目分类:动态规划,单调队列优化

题意:

给出一个有障碍的网格图和一个可移动的棋子,每个时间段中移动的方向是确定的,可以控制他的停止,问最多可以走多少格。

题解:

使用动态规划dp[i][j][k]表示到了第i行第j列时间为k最多走几格,发现状态数过多。

将最后一位从时间改为时间段,这样需要额外的200转移时间。

可以发现转移满足单调队列优化规律。

程序:

#include<cstdio>
#include<algorithm>
using namespace std;
int dp[210][210][210];
char str[210][210];
int n,m,k,tx,ty,x1,x2,x3;
int a[210],bar[210];/*
struct node
{
	int lef[12000],rig[12000],val[12000];
	inline void build(int x,int le,int ri)
	{
		lef[x]=le;
		rig[x]=ri;
		if(le==ri)
		{
			val[x]=a[le];
			return;
		}
		build(x*2,le,(le+ri)/2);
		build(x*2+1,(le+ri)/2+1,ri);
		val[x]=max(val[x*2],val[x*2+1]);
	}
	inline int query(int x,int le,int ri)
	{
		if(le>ri)return -1200000;
		if(le<=lef[x]&&ri>=rig[x])return val[x];
		int ss=-1200000;
		if(le<=rig[x*2])ss=max(ss,query(x*2,le,ri));
		if(ri>=lef[x*2+1])ss=max(ss,query(x*2+1,le,ri));
		return ss;
	}
}sgt;
inline void up(int x,int last)
{
	for (int j=1;j<=m;j++)
	{
		for (int i=1;i<=n;i++)
		{
			a[i]=dp[x-1][i][j]+i;
		}
		sgt.build(1,1,n);
		bar[n+1]=n+1;
		for (int i=n;i>=1;i--)
		{
			if(str[i][j]=='x')
			bar[i]=i;
			else
			bar[i]=bar[i+1];
		}
		for (int i=n;i>=1;i--)
		{
			int tp=bar[i];
			if(bar[i]-i>last+1)tp=i+last+1;
			dp[x][i][j]=sgt.query(1,i,tp-1)-i;
		}
	}
}
inline void down(int x,int last)
{
	for (int j=1;j<=m;j++)
	{
		for (int i=1;i<=n;i++)
		{
			a[i]=dp[x-1][i][j]-i;
		}
		sgt.build(1,1,n);
		bar[0]=0;
		for (int i=1;i<=n;i++)
		{
			if(str[i][j]=='x')
			bar[i]=i;
			else
			bar[i]=bar[i-1];
		}
		for (int i=1;i<=n;i++)
		{
			int tp=bar[i];
			if(i-bar[i]>last+1)tp=i-last-1;
			dp[x][i][j]=sgt.query(1,tp+1,i)+i;
		}
	}
}
inline void left(int x,int last)
{
	for (int j=1;j<=n;j++)
	{
		for (int i=1;i<=m;i++)
		{
			a[i]=dp[x-1][j][i]+i;
		}
		sgt.build(1,1,m);
		bar[m+1]=m+1;
		for (int i=m;i>=1;i--)
		{
			if(str[j][i]=='x')
			bar[i]=i;
			else
			bar[i]=bar[i+1];
		}
		for (int i=m;i>=1;i--)
		{
			int tp=bar[i];
			if(bar[i]-i>last+1)tp=i+last+1;
			dp[x][j][i]=sgt.query(1,i,tp-1)-i;
		}
	}
}
inline void right(int x,int last)
{
	for (int j=1;j<=n;j++)
	{
		for (int i=1;i<=m;i++)
		{
			a[i]=dp[x-1][j][i]-i;
		//	printf("a:::%d %d %d\n",j,i,a[i]);
		}
		sgt.build(1,1,m);
		bar[0]=0;
		for (int i=1;i<=m;i++)
		{
			if(str[j][i]=='x')
			bar[i]=i;
			else
			bar[i]=bar[i-1];
		//	printf("%d %d %d\n",j,i,bar[i]);
		}
		for (int i=1;i<=m;i++)
		{
			int tp=bar[i];
			if(i-bar[i]>last+1)tp=i-last-1;
		//	printf("%d %d %d\n",j,i,tp);
			dp[x][j][i]=sgt.query(1,tp+1,i)+i;
		}
	}
}*/
int l,r,q[12000];
inline void up(int x,int last)
{
	for (int j=1;j<=m;j++)
	{
		l=0;r=-1;
		for (int i=n;i>=1;i--)
		{
			if(str[i][j]=='x'){l=0;r=-1;}
			else
			{
				while (l<=r&&dp[x-1][q[r]][j]+q[r]<=dp[x-1][i][j]+i)r--;
				r++;
				q[r]=i;
				while (q[l]-i>last)l++;
				dp[x][i][j]=dp[x-1][q[l]][j]+q[l]-i;
			}
		}
	}
}
inline void down(int x,int last)
{
	for (int j=1;j<=m;j++)
	{
		l=0;r=-1;
		for (int i=1;i<=n;i++)
		{
			if(str[i][j]=='x'){l=0;r=-1;}
			else
			{
				while (l<=r&&dp[x-1][q[r]][j]-q[r]<=dp[x-1][i][j]-i)r--;
				r++;
				q[r]=i;
				while (i-q[l]>last)l++;
				dp[x][i][j]=dp[x-1][q[l]][j]-q[l]+i;
			}
		}
	}
}
inline void left(int x,int last)
{
	for (int j=1;j<=n;j++)
	{
		l=0;r=-1;
		for (int i=m;i>=1;i--)
		{
			if(str[j][i]=='x'){l=0;r=-1;}
			else
			{
				while (l<=r&&dp[x-1][j][q[r]]+q[r]<=dp[x-1][j][i]+i)r--;
				r++;
				q[r]=i;
				while (q[l]-i>last)l++;
				dp[x][j][i]=dp[x-1][j][q[l]]+q[l]-i;
			}
		}
	}
}
inline void right(int x,int last)
{
	for (int j=1;j<=n;j++)
	{
		l=0;r=-1;
		for (int i=1;i<=m;i++)
		{
			if(str[j][i]=='x'){l=0;r=-1;}
			else
			{
				while (l<=r&&dp[x-1][j][q[r]]-q[r]<=dp[x-1][j][i]-i)r--;
				r++;
				q[r]=i;
				while (i-q[l]>last)l++;
				dp[x][j][i]=dp[x-1][j][q[l]]-q[l]+i;
			}
		}
	}
}
int main()
{
	scanf("%d %d %d %d %d",&n,&m,&tx,&ty,&k);
	for (int i=1;i<=n;i++)
	{
		scanf("%s",str[i]+1);
	}
	for (int i=0;i<=k;i++)
	{
		for (int j=1;j<=n;j++)
		{
			for (int l=1;l<=m;l++)
			{
				dp[i][j][l]=-1200000;
			}
		}
	}
	dp[0][tx][ty]=0;
	for (int i=1;i<=k;i++)
	{
		scanf("%d %d %d",&x1,&x2,&x3);
		if(x3==1)up(i,x2-x1+1);
		if(x3==2)down(i,x2-x1+1);
		if(x3==3)left(i,x2-x1+1);
		if(x3==4)right(i,x2-x1+1);
	}
	int ans=0;
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=m;j++)
		{
			ans=max(ans,dp[k][i][j]);
		}
	}printf("%d\n",ans);
	return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter