Codeforces Round #355 (Div. 2) Vanya and Treasure

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #355 (Div. 2) Vanya and Treasure相关的知识,希望对你有一定的参考价值。

这是一道很显然的DP题目,状态转移在题目中也很直接,就是从k-1到k,然而如果count[k-1]*cnt[k],那么时间复杂度就会很大,本来的复杂度应该是O(p*n*n*m*m),用DP的话会很TLE,看了大牛的解释后,是在p<sqrt(mn)时候用DP,之后如果p>sqrt(nm)的话就用BFS,这样用均摊分析可以计算其时间复杂度(后边我打算写一篇关于均摊分析的博文)。

#include  <iostream>
#include  <cstdio>
#include  <cstring>
#include  <vector>
#include  <queue>
#include  <cmath>
#include  <algorithm>
#define X first
#define Y second
#define mp make_pair
#define Pair pair<int,pair<int,int> >
using namespace std;
const int INF=99999999;
const int maxn=305;
const int maxp=maxn*maxn;
const int dx[4]={0,1,0,-1},dy[4]={-1,0,1,0};
int n,m,p,a[maxn][maxn],dp[maxn][maxn];
int d[maxn][maxn];
struct Node
{
	int x,y;
	Node(int x,int y)
	{
		this->x=x;
		this->y=y;
	}
};
vector<Pair > lst;
vector<Node> G[maxp];
bool in_range(int x,int y)
{
	if(x>=1&&x<=n&&y>=1&&y<=m)
		return true;
	return false;
}
int main()
{
	for(int i=0;i<maxn;i++)
		for(int j=0;j<maxn;j++)
			dp[i][j]=INF;
	scanf("%d%d%d",&n,&m,&p);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			scanf("%d",&a[i][j]);
			G[a[i][j]].push_back(Node(i,j));
			if(a[i][j]==1)
			{
				dp[i][j]=(i-1)+(j-1);
			}
		}
	}
	for(int k=2;k<=p;k++)
	{ 
		if(G[k].size()*G[k-1].size()<n*m)
		{
			for(int i=0;i<G[k].size();i++)
			{
				Node& p1=G[k][i];
				for(int j=0;j<G[k-1].size();j++)
				{
					Node& p2=G[k-1][j];
					int dist=abs(p1.x-p2.x)+abs(p1.y-p2.y);
					dp[p1.x][p1.y]=min(dp[p1.x][p1.y],dp[p2.x][p2.y]+dist);
				}
			}
		}
		else
		{
			for(int i=0;i<=n;i++)
				for(int j=0;j<=m;j++)
					d[i][j]=-1;
			queue<Pair > que;
			while(!que.empty())
				que.pop();
			lst.clear();
			for(int i=0;i<G[k-1].size();i++)
			{
				int x=G[k-1][i].x;
				int y=G[k-1][i].y;
				lst.push_back(mp(dp[x][y],mp(x,y)));
			}
			int cnt(0),sum(G[k].size());
			sort(lst.begin(),lst.end());
			for(int i=0;i<lst.size();i++)
			{
				que.push(lst[i]);
				d[lst[i].Y.X][lst[i].Y.Y]=lst[i].X;
			}
			while(!que.empty())
			{
				Pair temp=que.front();
				que.pop();
				for(int i=0;i<4;i++)
				{
					int tx=temp.Y.X+dx[i];
					int ty=temp.Y.Y+dy[i];
					if(in_range(tx,ty))
					{
						if(d[tx][ty]==-1||d[tx][ty]>temp.X+1)
						{
							d[tx][ty]=temp.X+1;
							que.push(mp(temp.X+1,mp(tx,ty)));
							if(a[tx][ty]==k)
							{
								dp[tx][ty]=min(dp[tx][ty],temp.X+1);
							}
						}
					}
				}
			}
		}
	}
	printf("%d\n",dp[G[p][0].x][G[p][0].y]);
	return 0;
}

  

以上是关于Codeforces Round #355 (Div. 2) Vanya and Treasure的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #355 (Div. 2)

Codeforces Round #355 (Div. 2)

Codeforces Round #355 (Div. 2) D. Vanya and Treasure 分治暴力

Codeforces Round #355 (Div. 2) Vanya and Label

Codeforces Round #355 (Div. 2) Vanya and Treasure

Codeforces Round #436 E. Fire(背包dp+输出路径)