一傻逼题调了两天。。

n<=30 * m<=30的地图,0表示可以放平台,1表示本来有平台,2表示不能走,3起点4终点,走路方式为象棋的日字,求:从起点走到终点,至少要放多少平台,以及放平台的方案数,无解-1。

方法一:其实能走直接平台的就可以直接走来走去,也就是算一个联通块。类似于tarjan,先把一大块缩成一点,然后连边走最短路。

错误!存在边权为0的边,会导致统计方案出现重复。比如:

圆圈走到三角形,直接走和绕一圈是一样的,但算了两次。

方法二:把0边去掉就行了。由于数据小,开个数组[a][b][c][d]表示a,b到c,d是否能通过填一块到达,这个数组只需对每个点做一次搜索就能出来。最后就是最短路啦。

不过边权为1,谁最短路会写迪杰呢?肯定bfs啦!

 #include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
//#include<iostream>
using namespace std; int n,m;
int a[][],can[][][][];
#define maxn 1011
#define maxm 10011
struct Edge{int tx,ty,next;}edge[maxn*maxn];int first[][],le=;
#define LL long long
void in(int sx,int sy,int tx,int ty)
{
Edge &e=edge[le];
e.tx=tx;e.ty=ty;
e.next=first[sx][sy];
first[sx][sy]=le++;
}
int nx,ny;
const int dx[]={,,,,-,-,-,-},dy[]={,-,,-,,-,,-};
bool vis[][];
void dfs(int x,int y)
{
vis[x][y]=;
for (int i=;i<;i++)
{
const int xx=x+dx[i],yy=y+dy[i];
if (xx< || xx>n || yy< || yy>m || can[nx][ny][xx][yy]
|| a[xx][yy]== || vis[xx][yy]) continue;
if (a[xx][yy]== || a[xx][yy]==)
{
can[nx][ny][xx][yy]=;
continue;
}
dfs(xx,yy);
}
}
const int inf=0x3f3f3f3f;
int dis[][];LL way[][];
struct qnode{int x,y;}q[maxn];int head,tail;
void bfs(int sx,int sy)
{
head=;tail=;q[].x=sx;q[].y=sy;
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
dis[i][j]=inf;
dis[sx][sy]=;way[sx][sy]=;
while (head!=tail)
{
const int nx=q[head].x,ny=q[head++].y;
for (int i=first[nx][ny];i;i=edge[i].next)
{
const Edge &e=edge[i];
if (dis[e.tx][e.ty]>dis[nx][ny]+)
{
dis[e.tx][e.ty]=dis[nx][ny]+;
way[e.tx][e.ty]=way[nx][ny];
q[tail].x=e.tx,q[tail++].y=e.ty;
}
else if (dis[e.tx][e.ty]==dis[nx][ny]+)
way[e.tx][e.ty]+=way[nx][ny];
}
}
}
int main()
{
scanf("%d%d",&n,&m);
int sx,sy,tx,ty;
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
{
scanf("%d",&a[i][j]);
if (a[i][j]==) sx=i,sy=j;
if (a[i][j]==) tx=i,ty=j;
}
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
{
memset(can[i][j],,sizeof(can[i][j]));
memset(vis,,sizeof(vis));
if (a[i][j]==) continue;
nx=i;ny=j;
dfs(i,j);
}
memset(first,,sizeof(first));
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
for (int k=;k<=n;k++)
for (int l=;l<=m;l++)
{
if (can[i][j][k][l])
{
in(i,j,k,l);
}
}
bfs(sx,sy);
if (dis[tx][ty]==inf) puts("-1");
else printf("%d\n%lld\n",dis[tx][ty]-,way[tx][ty]);
return ;
}

最新文章

  1. 构建自己的PHP框架--抽象框架的内容
  2. UnionPay,ChinaPay 最新 银联支付接口C#\Asp.net\MVC 版本
  3. POJ 2763 Housewife Wind (树链剖分 有修改单边权)
  4. PHP开篇之环境的搭建
  5. (转)[老老实实学WCF] 第二篇 配置WCF
  6. JavaScript基本概念(对象)
  7. 可运行jar包调用exe可运行文件,子进程阻塞
  8. Python基础之字符编码
  9. Hibernate(十三):HQL查询(二)
  10. 【安卓开发】为什么不能往Android的Application对象里存储数据
  11. SharePoint中你不知道的图片库(实战)
  12. 阿里P8架构师讲述:3—5年程序员的发展和出路在哪里?
  13. Java 创建线程/停止线程
  14. 爬取伯乐在线文章(二)通过xpath提取源文件中需要的内容
  15. [转载]要提高SQL查询效率where语句条件的先后次序应如何写
  16. STM32的HAL库中的DMA_FLAG_TCIF3_7等几个宏定义的含义
  17. Linux:修改和删除已有变量
  18. HDU5629:Clarke and tree(DP,Prufer)
  19. Java多线程之可见性与原子性——synchronized VS volatile
  20. loadrunner socket协议问题归纳(4)---buffer接收变长和定长的数据

热门文章

  1. SEO &amp; HTML语义化
  2. android动画之通过子线程来实现动画
  3. 毕业设计:HomeFragment(一)
  4. PMP项目管理学习笔记(12)——范围管理之创建工作分解结构(WBS)
  5. 登录脚本重构by封装
  6. mybatis中存储过程的调用
  7. vue 组件内 directives指令的调用方式 &lt;base-table v-auto-height:tableHeight=&quot;{vm:this, diffHeight:ahTable.diffHeight}&quot;
  8. js实现复制input的value到剪切板
  9. JavaEE-09 Ajax与jQuery在JavaEE项目中的使用
  10. postman使用--批量执行测试用例和数据驱动