码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2016-06-07 01:03:09      阅读:262      评论:0      收藏:0      [点我收藏+]

标签:

这是一道很显然的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

标签:

原文地址:http://www.cnblogs.com/northsnow95/p/5565548.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!