[ USACO 2007 FEB ] Lilypad Pond (Gold)
\(\\\)
\(Description\)
一张\(N\times M\)的网格,已知起点和终点,其中有一些地方是落脚点,有一些地方是空地,还有一些地方是坏点。
现在要从起点到终点,每次移动走日字\((\)横一纵二或横二纵一\()\),其中只能经过起点、终点、落脚点。
现在可以开发任意个数的空地变为落脚点,问找到合法路径最少需要开发多少个空地,以及最少开发的方案数。
注意,只要有一个被开发的空地不同即视为不同的方案。
- \(N,M\in [1,30]\)
\(\\\)
\(Solution\)
不得不说建图相当妙。
先考虑一种直接的建图方式,落脚点和起点向可以直接到达的空地或落脚点连\(0\)边,空地向可以直接到达的空地或落脚点连\(1\)边,最短路计数。我们发现这样的最短路长度是没有问题的,但是最短路方案数是有问题的。
因为像这样,在两个空地之间可以有多个可以用于转移的原有落脚点时,方案数就会多算好几倍。

\(\\\)
然后发现,貌似中间经过已有的落脚点不同并不会影响两点间的最短路长度和计数,所以不妨直接忽略掉所有原有的落脚点以及坏点,只考虑包含起点、终点、空地的图,以下将起点终点视为空地。
建图可以对每一个合法的点\(BFS\)一遍,统计出该点在经过若干个\((\)可以不经过\()\)原有落脚点可以到达的空地,显然中间经过落脚点是没有代价的,而在开始\(BFS\)的点处需要花费代价建造落脚点,所以边权为\(1\)。特殊的,起点并不需要代价,所以起点连出去的边边权为\(0\)。此时最短路条数显然就是方案数了。
\(\\\)
\(Code\)
最短路计数又傻了....注意不是加一而是累加,以及重置的时候不是\(1\),而是直接继承
注意边表的大小需要开 long long 差评
#include<cmath>
#include<queue>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 50
#define M 60010
#define R register
#define gc getchar
#define inf 200000000
using namespace std;
typedef long long ll;
inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
}
bool vis[N*N];
const int dx[8]={1,1,-1,-1,2,2,-2,-2};
const int dy[8]={2,-2,2,-2,1,-1,1,-1};
ll ts[N*N];
int n,m,s,t,tot,dis[N*N];
int cnt,num[N][N],mp[N][N],hd[N*N];
struct edge{int w,to,nxt;}e[M<<1];
inline void add(int u,int v,int w){
e[++tot].to=v; e[tot].w=w;
e[tot].nxt=hd[u]; hd[u]=tot;
}
queue<pair<int,int> > q;
inline void bfs(int ux,int uy,int w){
memset(vis,0,sizeof(vis));
q.push(make_pair(ux,uy)); vis[num[ux][uy]]=1;
while(!q.empty()){
int x=q.front().first;
int y=q.front().second; q.pop();
for(R int i=0,nx,ny;i<8;++i){
nx=x+dx[i]; ny=y+dy[i];
if(nx<1||nx>n||ny<1||ny>m||vis[num[nx][ny]]) continue;
vis[num[nx][ny]]=1;
if(mp[nx][ny]!=1&&mp[nx][ny]!=2) add(num[ux][uy],num[nx][ny],w);
else if(mp[nx][ny]==1) q.push(make_pair(nx,ny));
}
}
}
queue<int> qs;
inline void SPFA(){
memset(vis,0,sizeof(vis));
for(R int i=1;i<=cnt;++i) dis[i]=inf;
qs.push(s); dis[s]=0; ts[s]=1ll;
while(!qs.empty()){
int u=qs.front();
qs.pop(); vis[u]=0;
for(R int i=hd[u],v;i;i=e[i].nxt)
if(dis[v=e[i].to]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w; ts[v]=ts[u];
if(!vis[v]) vis[v]=1,qs.push(v);
}
else if(dis[v]==dis[u]+e[i].w) ts[v]+=ts[u];
}
}
int main(){
n=rd(); m=rd();
for(R int i=1;i<=n;++i)
for(R int j=1;j<=m;++j){
mp[i][j]=rd();
num[i][j]=++cnt;
if(mp[i][j]==3) s=cnt;
if(mp[i][j]==4) t=cnt;
}
for(R int i=1;i<=n;++i)
for(R int j=1;j<=m;++j)
if(mp[i][j]==0||mp[i][j]>1) bfs(i,j,(mp[i][j]!=3));
SPFA();
if(dis[t]<inf) printf("%d\n%lld",dis[t],ts[t]);
else puts("-1");
return 0;
}
[ USACO 2007 FEB ] Lilypad Pond (Gold)的更多相关文章
- [ USACO 2007 FEB ] Lilypad Pond (Silver)
\(\\\) \(Description\) 一张\(N\times M\)的网格,已知起点和终点,其中有一些地方是落脚点,有一些地方是空地,还有一些地方是坏点. 现在要从起点到终点,每次移动走日字\ ...
- BZOJ 1632: [Usaco2007 Feb]Lilypad Pond
题目 1632: [Usaco2007 Feb]Lilypad Pond Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 390 Solved: 109[ ...
- 1632: [Usaco2007 Feb]Lilypad Pond
1632: [Usaco2007 Feb]Lilypad Pond Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 404 Solved: 118[Sub ...
- 「BZOJ 1698」「USACO 2007 Feb」Lilypad Pond 荷叶池塘「最短路」
题解 从一个点P可以跳到另一个点Q,如果Q是水这条边就是1,如果Q是荷叶这条边权值是0.可以跑最短路并计数 问题是边权为0的最短路计数没有意义(只是荷叶的跳法不同),所以我们两个能通过荷叶间接连通的点 ...
- bzoj1632 [Usaco2007 Feb]Lilypad Pond
Description Farmer John 建造了一个美丽的池塘,用于让他的牛们审美和锻炼.这个长方形的池子被分割成了 M 行和 N 列( 1 ≤ M ≤ 30 ; 1 ≤ N ≤ 30 ) 正方 ...
- BZOJ1632: [Usaco2007 Feb]Lilypad Pond SPFA+最短路计数
Description 为了让奶牛们娱乐和锻炼,农夫约翰建造了一个美丽的池塘.这个长方形的池子被分成了M行N列个方格(1≤M,N≤30).一些格子是坚固得令人惊讶的莲花,还有一些格子是岩石,其余的只是 ...
- 【BZOJ】1632: [Usaco2007 Feb]Lilypad Pond(bfs)
http://www.lydsy.com/JudgeOnline/problem.php?id=1632 我简直是个sb... ... bfs都不会写.. 算方案还用2个bfs! 都不会整合到一个! ...
- BZOJ 1632 [Usaco2007 Feb]Lilypad Pond:spfa【同时更新:经过边的数量最小】【路径数量】
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1632 题意: 有一个n*m的池塘.0代表水,1代表荷花,2代表岩石,3代表起点,4代表终点 ...
- BZOJ1698: [Usaco2007 Feb]Lilypad Pond 荷叶池塘
一傻逼题调了两天.. n<=30 * m<=30的地图,0表示可以放平台,1表示本来有平台,2表示不能走,3起点4终点,走路方式为象棋的日字,求:从起点走到终点,至少要放多少平台,以及放平 ...
随机推荐
- 修改mysql root用户密码(忘记密码)
vi /etc/my.cnf,在[mysqld]中添加 skip-grant-tables 例如: [mysqld] skip-grant-tables datadir=/var/lib/mysql ...
- idea中javaweb的mysql8.0.15配置问题
mysql8.0.x以后的版本在连接数据库的时候有些不同. 首先: Class.forName("com.mysql.cj.jdbc.Driver"); 其次: DriverMan ...
- Nginx/Spring:增加上传文件尺寸限制
Nginx: 1. vi /etc/nginx/nginx.config 2. 在server中增加如下行 # set client body size to 20M # client_max_bod ...
- PB MD5
适用环境:powerbuilder 10.0以后的版本号 window server2003以后的測试可用 PB也能够调用系统自带的DLL 实现MD5 当中md5file对大附件的处理速度也比第三方 ...
- python模块之 paramiko(转载)
paramiko模块提供了ssh及sft进行远程登录服务器执行命令和上传下载文件的功能.这是一个第三方的软件包,使用之前需要安装. 1 基于用户名和密码的 sshclient 方式登录 # 建立一个s ...
- iPhone微信防止撤销插件开发
导语: 随着移动时代的发展以及微信的普及流行,越来越多的用户使用微信发送消息,但经常出现撤销消息的情况.因此需要一款微信防止消息撤回插件,微信用户可以防止对方撤回消息,看到对方发出的任何消息,妈妈再也 ...
- make常见报错原因分析
1 No rule to make target ‘xxx’ 原因一般是'xxx'文件不存在,首先应该去相应的目录检查文件是否存在.
- 【Codeforces】716D Complete The Graph
D. Complete The Graph time limit per test: 4 seconds memory limit per test: 256 megabytes input: sta ...
- 【转载】limits.h
limits.h专门用于检测整型数据数据类型的表达值范围. <limits.h>主要提供对整型和字符型范围的限制的宏,同样没有指定类型和函数的定义. 1.整型宏如下表: 2.字符型宏如下表 ...
- SQLALchemy之创建表,删除表
1.创建引擎 "数据库+第三方模块://用户名:密码@数据库服务端IP:端口号/数据库名?编码" engine = create_engine( "mysql+pymys ...