题意:有n个字符,第一列有m个,类推下去。选择一个光标位置,使得他到每一个字符的期望最小。
第一行不能向上走,最下行不能向下走,其他跟诺基亚的类似。求最小期望。并输出最短路。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
using namespace std;
const int N = 1009;
int n,m;
struct nod{
int x,y;
}nex[N][N][4];
int dis[N][N];
const int INF = 0x3f3f3f3f;
void init()
{
int row = (n-1)/m+1,las = (n-1)%m+1;
for(int i=0;i<row;i++)
for(int j=0;j<m;j++)
{
nex[i][j][0].x = i,nex[i][j][0].y = j-1;
nex[i][j][1].x = i+1,nex[i][j][1].y = j;
nex[i][j][2].x = i,nex[i][j][2].y = j+1;
nex[i][j][3].x = i-1,nex[i][j][3].y = j;
}
//0
nex[0][0][0].x = row-1,nex[0][0][0].y = las-1;
for(int i=1;i<row;i++) nex[i][0][0].x = i-1,nex[i][0][0].y = m-1;
//2
for(int i=0;i<row;i++) nex[i][m-1][2].x = i+1,nex[i][m-1][2].y = 0;
//1,3
if(row==1)
{
for(int i=0;i<n;i++)
nex[0][i][1].x =0,nex[0][i][3].x = 0;
}
else
{
//1
for(int i=0;i<m;i++)
if(i<las)
{
nex[row-1][i][1].x = row-1,nex[row-1][i][1].y = i;
}else
{
nex[row-2][i][1].x = row-2,nex[row-2][i][1].y = i;
}
//3
for(int i=0;i<m;i++)
if(i<las)
{
nex[0][i][3].x = 0,nex[0][i][3].y = i;
}else
{
nex[0][i][3].x = 0,nex[0][i][3].y = i;
}
}
//last
nex[row-1][las][2].x = 0,nex[row-1][las][2].y = 0;
}
queue<nod> que;
nod ans;
int mindis(int x,int y)
{
while(!que.empty()) que.pop();
nod e,t;
e.x = x,e.y = y;
que.push(e);
memset(dis,INF,sizeof(dis));
dis[e.x][e.y] = 0;
while(!que.empty())
{
e = que.front();
que.pop();
int d = dis[e.x][e.y];
int tx,ty;
for(int i=0;i<4;i++)
{
tx = nex[e.x][e.y][i].x;
ty = nex[e.x][e.y][i].y;
if(dis[tx][ty]>d+1)
{
dis[tx][ty] =d+1;
t.x = tx,t.y = ty;
que.push(t);
}
}
}
int ret = 0;
for(int i=0;i<n;i++)
{
ret+=dis[i/m][i%m];
}
return ret;
}
void solve()
{
int tmp = INF;
for(int i=0;i<n;i++)
{
int x = i/m,y = i%m;
memset(dis,INF,sizeof(dis));
int k =mindis(x,y);
if(tmp>k)
{
tmp = k;
ans.x = x,ans.y =y;
}
}
printf("Mean = %.2lf\n",1.0*tmp/n);
mindis(ans.x,ans.y);
for(int i=0;i<n;i++)
{
if(i&&i%m==0) printf("\n");
if(i%m) printf(" ");
printf("%d",dis[i/m][i%m]);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
scanf("%d%d",&n,&m);
if(m>n) m = n;
init();
solve();
return 0;
}