旅行 (分别考虑不同方向曼哈顿距离和)

第二题:旅行(journey)

时间限制:1秒

内存限制:256MB

输入:journey.in

输出:journey.out

问题描述

给定一个n行m列的字符矩阵,’.’代表空地,’X’代表障碍。移动的规则是:每秒钟以上下左右四个方向之一移动一格,不能进入障碍。计算:在空地中随机选择起点和终点(可以重合,此时最短耗时为0),从起点移动到终点最短耗时的平均值。

每一行每一列至多有1个障碍,并且障碍不在对角线方向相邻。以下矩阵是不合法的:

.X

X.

输入

第一行两个整数n, m。。

接下来n行,每行m个字符’.’或’X’。在50%的数据中,保证每个字符都是’.’。

输出

平均耗时,保留4位小数,四舍五入。数据保证在范围之内输出一致,Ans是标准答案。

样例输入

2 2

..

.X

样例输出

0.8889

 

 

 

 

 

yle�� sth�p�ive;top:3.0pt;mso-text-raise:-3.0pt'>。所有信息按照从左到右的顺序给出。在50%的数据中,。

输出

第一行:出列的总对数k。接下来输出k行,每行是两个整数。按跳舞顺序输出,两个整数代表这一对舞伴的编号(按输入顺序从左往右1至n编号)。请先输出较小的整数,再输出较大的整数。

样例输入

4

BGBG

4 2 4 3

样例输出

2

3 4

1 2

样例输入

4

BGBB

1 1 2 3

样例输出

1

1 2



解1:

Dp出所有平地曼哈顿距离和(全T)


#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<functional>
#include<algorithm>
#include<stack>
using namespace std;
#define MAXN (1000+10)
#define DELTA (0.00000001)
#define F (10000000)
int n,m;
char s[2000];
int a[MAXN],b[MAXN];
long long f[MAXN][MAXN];
int calc(int l,int r,int n)
{
	return 2*(l-1)*(n-r);	
}


int main()
{
	freopen("journey.in","r",stdin);
	freopen("journey.out","w",stdout);

/*	long long ans=0;
	scanf("%d%d",&n,&m);
	for (int n=1;n<=10;n++)
	{
	for (int m=1;m<=10;m++)
	{
	long long ans=0;
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
			for (int k=1;k<=n;k++)
				for (int l=1;l<=m;l++)
					ans+=abs(i-k)+abs(j-l);
	
	printf("%d ",ans);
	}
	cout<<endl;
}
*/

	memset(f,0,sizeof(f));
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	
	long long tot=0;
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++)
	{
		scanf("%s",s);
		for (int j=0;j<m;j++) 
			if (s[j]=='X')
			{
				tot++;
				a[i]=j+1;
				b[j+1]=i;
				break;
			}		
	}
	tot=n*m-tot;

//	for (int i=1;i<=n;i++) cout<<a[i]<<' ';
	
	
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
		{
			f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+i*j*(i+j-2)+(i-1)*(j-1)*(i+j);
			if (a[i]==j) f[i][j]-=+i*j*(i+j-2);
			else 
			{
				for (int k=1;k<=i;k++)
				 if (a[k]&&a[k]<=j) 
				 f[i][j]-=2*(i-k+j-a[k]);
				
				
				if (a[i]&&a[i]<j)
					 f[i][j]-=(i-1)*(i+2*(j-a[i]));
				if (b[j]&&b[j]<i)
					 f[i][j]-=(j-1)*(j+2*(i-b[j]));
				if (a[i]&&a[i]<j&&b[j]&&b[j]<i) 
					f[i][j]+=2*((j-a[i])+(i-b[j]));
				
			}
//			cout<<f[i][j]<<endl;
		}
/*	
	for (int i=0;i<=n;i++){
		for (int j=0;j<=m;j++)
			cout<<f[i][j]<<' ';
		cout<<'\n';
	}*/
	
	long long ans=f[n][m];
//	cout<<ans<<endl;
	for (int i=1;i<=n;i++)
		if (a[i])
		{
			ans+=2*calc(a[i],a[i],m);
			if (i>1&&a[i-1])
			{
				int j=i-1;
				if (a[j]<a[j+1])
				{
					while (j>0&&a[j]&&a[j]<a[j+1]) {ans+=2*calc(a[j],a[i],m);j--;}										
				}/*
				else if (a[j]>a[j+1])
				{
					while (j>0&&a[j]>a[j+1]) {ans+=2*calc(a[i],a[j],m);j--;}										
				}	*/		
			}			
			if (i<n&&a[i+1])
			{
				int j=i+1;
				if (a[j]<a[j-1])
				{
					while (j<=n&&a[j]&&a[j]<a[j-1]) {ans+=2*calc(a[j],a[i],m);j++;}										
				}/*
				else if (a[j]>a[j-1])
				{
					while (j<=n&&a[j]>a[j-1]) {ans+=2*calc(a[i],a[j],m);j++;}										
				}*/			
			}								
		}
	for (int i=1;i<=m;i++)
		if (b[i])
		{
			ans+=2*calc(b[i],b[i],n);
			if (i>1&&b[i-1])
			{
				int j=i-1;
				if (b[j]<b[j+1])
				{
					while (j>0&&b[j]&&b[j]<b[j+1]) {ans+=2*calc(b[j],b[i],n);j--;}										
				}/*
				else if (b[j]>b[j+1])
				{
					while (j>0&&b[j]>b[j+1]) {ans+=2*calc(b[i],b[j],n);j--;}										
				}*/			
			}			
			if (i<m&&b[i+1])
			{
				int j=i+1;
				if (b[j]<b[j-1])
				{
					while (j<=m&&b[j]&&b[j]<b[j-1]) {ans+=2*calc(b[j],b[i],n);j++;}										
				}/*
				else if (b[j]>b[j-1])
				{
					while (j<=m&&b[j]>b[j-1]) {ans+=2*calc(b[i],b[j],n);j++;}										
				}*/			
			}								
		}
//	cout<<ans<<endl;
	double _ans=double(ans)/double(tot)/double(tot);
	printf("%.4lf\n",_ans);


	while (1);

	return 0;
	
	
}



正解

找一格,向前后搜 曼哈顿距离和分别考虑纵横方向


#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<functional>
#include<algorithm>
#include<stack>
using namespace std;
#define MAXN (1000+10)
#define DELTA (0.00000001)
#define F (10000000)
int n,m;
char s[2000];
int a[MAXN],b[MAXN];
//long long f[MAXN][MAXN];
int calc(int l,int r,int n)
{
	return 2*(l-1)*(n-r);	
}


int main()
{
	freopen("journey.in","r",stdin);
	freopen("journey.out","w",stdout);

//	memset(f,0,sizeof(f));
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	
	long long tot=0;
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++)
	{
		scanf("%s",s);
		for (int j=0;j<m;j++) 
			if (s[j]=='X')
			{
				tot++;
				a[i]=j+1;
				b[j+1]=i;
				break;
			}		
	}
	tot=n*m-tot;

//	for (int i=1;i<=n;i++) cout<<a[i]<<' ';
	
	/*
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
		{
			f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+i*j*(i+j-2)+(i-1)*(j-1)*(i+j);
			if (a[i]==j) f[i][j]-=+i*j*(i+j-2);
			else 
			{
				for (int k=1;k<=i;k++)
				 if (a[k]&&a[k]<=j) 
				 f[i][j]-=2*(i-k+j-a[k]);
				
				
				if (a[i]&&a[i]<j)
					 f[i][j]-=(i-1)*(i+2*(j-a[i]));
				if (b[j]&&b[j]<i)
					 f[i][j]-=(j-1)*(j+2*(i-b[j]));
				if (a[i]&&a[i]<j&&b[j]&&b[j]<i) 
					f[i][j]+=2*((j-a[i])+(i-b[j]));
				
			}
//			cout<<f[i][j]<<endl;
		}
/*	
	for (int i=0;i<=n;i++){
		for (int j=0;j<=m;j++)
			cout<<f[i][j]<<' ';
		cout<<'\n';
	}*/

	long long ans=0;
	for (int i=1;i<n;i++)
		for (int j=i+1;j<=n;j++)
			ans+=(m-(a[i]>0))*(m-(a[j]>0))*(j-i);
	for (int i=1;i<m;i++)
		for (int j=i+1;j<=m;j++)
			ans+=(n-(b[i]>0))*(n-(b[j]>0))*(j-i);
	ans*=2;	
	
	
	
	
	
//	long long ans=f[n][m];
//	cout<<ans<<endl;
	for (int i=1;i<=n;i++)
		if (a[i])
		{
			ans+=2*calc(a[i],a[i],m);
			if (i>1&&a[i-1])
			{
				int j=i-1;
				if (a[j]<a[j+1])
				{
					while (j>0&&a[j]&&a[j]<a[j+1]) {ans+=2*calc(a[j],a[i],m);j--;}										
				}
			}			
			if (i<n&&a[i+1])
			{
				int j=i+1;
				if (a[j]<a[j-1])
				{
					while (j<=n&&a[j]&&a[j]<a[j-1]) {ans+=2*calc(a[j],a[i],m);j++;}										
				}
			}								
		}
	for (int i=1;i<=m;i++)
		if (b[i])
		{
			ans+=2*calc(b[i],b[i],n);
			if (i>1&&b[i-1])
			{
				int j=i-1;
				if (b[j]<b[j+1])
				{
					while (j>0&&b[j]&&b[j]<b[j+1]) {ans+=2*calc(b[j],b[i],n);j--;}										
				}
			}			
			if (i<m&&b[i+1])
			{
				int j=i+1;
				if (b[j]<b[j-1])
				{
					while (j<=m&&b[j]&&b[j]<b[j-1]) {ans+=2*calc(b[j],b[i],n);j++;}										
				}
			}								
		}
//	cout<<ans<<endl;
	double _ans=double(ans)/double(tot)/double(tot);
	printf("%.4lf\n",_ans);


//	while (1);

	return 0;
	
	
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值