内容目录
第二题:旅行(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("%.4lfn",_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("%.4lfn",_ans); // while (1); return 0; }