记录编号 321891 评测结果 AAAAAAAAAAAAAA
题目名称 [USACO Feb07] 银色莲花池 最终得分 100
用户昵称 GravatarLOSER 是否通过 通过
代码语言 C++ 运行时间 0.156 s
提交时间 2016-10-14 07:51:32 内存使用 21.13 MiB
显示代码纯文本
/*
	Name: 银色莲花池 
	Author: LOSER ! ! !   
	Date: 14/10/16 07:42
	Description: 
		前两问很好解决 一遍宽搜可以很好的解决问题
		但是关键在第三问 要求输出方案(记住这一个教训方案数很可能需要开longlong甚至是写高精度)
		开始时想的是一遍宽搜跑出答案但这显然不现实 因为vis数组会很好的帮你去重
		于是又想到了用一个f[x][y][step][ned]表示在一个点用step布 添加ned荷叶的方案数虽然这可以很好的
		计算所有情况,但是也很好的超过了内存限制,迫不得已看了一下题解 -_-|||
		由于是最短距离到达终点 所以我们可以用 dis[x][y][ned] 表示用ned荷叶到达(x,y) 所用的最短距离
		way[x][y][ned] 表示方案数 于是乎得出了答案 
*/
#include <queue> 
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 35
#define maxm maxn*maxn
#define LL long long
#define inf 0x7f7f7f7f
LL n,m,ans=inf,num=inf,cnt,a[maxn][maxn],startx,starty,endx,endy;
LL st[8][2]={{-2,1},{-1,2},{2,1},{1,2},{-2,-1},{-1,-2},{1,-2},{2,-1}};
struct Node{
	LL x,y,step,ned;
	Node(LL A,LL B,LL C,LL D){
		x=A,y=B,step=C,ned=D;
	}
};
queue<Node> q;
bool vis[maxn][maxn][maxm],Check;
LL dis[maxn][maxn][maxm],way[maxn][maxn][maxm];
void Bfs(){
	while( !q.empty() ){
		Node temp=q.front(); q.pop();
		if(temp.ned>num) continue;
		for(LL i=0;i<8;i++){
			LL xx=temp.x+st[i][0],yy=temp.y+st[i][1];
			if(xx<1||yy<1||xx>n||yy>m)continue;
			if(a[xx][yy]==2)continue;
			if(a[xx][yy]==4){
				Check=1;
				if(num>temp.ned){
					num=temp.ned;
					ans=temp.step+1;
					continue;
				}
				if(num==temp.ned){
					if(ans>temp.step+1){
						ans=temp.step+1;
						continue;
					}
				}
			}
			if(a[xx][yy]==1 && !vis[xx][yy][temp.ned]){				
				q.push(Node(xx,yy,temp.step+1,temp.ned));
				vis[xx][yy][temp.ned]=1;
			}
			if(a[xx][yy]==0 && !vis[xx][yy][temp.ned+1] ){
				q.push(Node(xx,yy,temp.step+1,temp.ned+1));
				vis[xx][yy][temp.ned+1]=1;
			}
		}
	}
	if(!Check) {printf("-1\n-1\n-1\n"); exit(0);}
	while( !q.empty() )q.pop();
	for(LL i=1;i<=n;i++)for(LL j=1;j<=m;j++)for(LL k=0;k<=num;k++) dis[i][j][k]=inf;
	memset(dis[startx][starty],0,sizeof(dis[startx][starty]));
	memset(way,0,sizeof(way));  way[startx][starty][0]=1;
	q.push(Node(startx,starty,0,0));
	a[endx][endy]=1;
	while( !q.empty() ){
		Node temp=q.front();q.pop();
		for(LL i=0;i<8;i++){
			LL xx=temp.x+st[i][0],yy=temp.y+st[i][1];
			if(xx<1||yy<1||xx>n||yy>m)continue;
			if(a[xx][yy]==2)continue;
			if(a[xx][yy]==1){
				if(temp.step+1<=ans && temp.ned<=num){
					if(temp.step+1<=dis[xx][yy][temp.ned]){
						if(temp.step+1<dis[xx][yy][temp.ned]){
							q.push(Node(xx,yy,temp.step+1,temp.ned));
							way[xx][yy][temp.ned]=0;
						}
						way[xx][yy][temp.ned]+=way[temp.x][temp.y][temp.ned];
						dis[xx][yy][temp.ned]=temp.step+1;
					}
				}
			}
			if(a[xx][yy]==0){
				if(temp.ned+1<=num && temp.step+1<=ans){
					if(temp.step+1<=dis[xx][yy][temp.ned+1]){
						if(temp.step+1<dis[xx][yy][temp.ned+1]){
							q.push(Node(xx,yy,temp.step+1,temp.ned+1));
							way[xx][yy][temp.ned+1]=0;
						}
						way[xx][yy][temp.ned+1]+=way[temp.x][temp.y][temp.ned];
						dis[xx][yy][temp.ned+1]=temp.step+1;		
					}
				}
			}
		}
	}
}
int main(){
	freopen("silvlily.in","r",stdin); freopen("silvlily.out","w",stdout);
	scanf("%lld%lld",&n,&m);
	LL x,y;
	for(LL i=1;i<=n;i++){
		for(LL j=1;j<=m;j++){
			scanf("%lld",&a[i][j]);
			if(a[i][j]==3){
				q.push(Node(i,j,0,0));
				vis[i][j][0]=1; startx=i;starty=j;
			}
			if(a[i][j]==4){endx=i,endy=j;}
		}
	}
	Bfs();
	printf("%lld\n%lld\n%lld\n",num,ans,way[endx][endy][num]);
	getchar(); getchar();
	return 0;
}