《随机题库练习10》D

HDU4166的一个进阶版吧.
思路:
首先联想到bfs的性质.
当我们搜素到(x,y)点时,那么这时的距离一定是到这个点最短的距离.
对于到X点的最短距离,可能会存在多个点到它的距离满足到x的最短距离.
但是这样的情况只是说明最短的路径很多,但是到x点的最短距离肯定是不变的.
因为从x->y的最短路径肯定是优于(其他到x的>最短路径的距离)->y的距离.
所以说我们只需要统计到这个点的路径和到这个点的最短路径相同的点,那么就说明可以构成一条最短路径.
然后联系起bfs的性质,当我们第一次搜素到这个点时,最短距离肯定就是这个距离.
然后最后进行一下判断,注意的是方向不同也算不同的状态.
然后方案数采用dp转移.
这里可以任意走X步,那么直接从1开始枚举步数.如果碰到炸弹或者出界,那么就说明不能再往前了,就退出该次循环.

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 105;
const int Mod = 1e6;
#define pi acos(-1)
#define INF 1e8
#define INM INT_MIN
#define pb(a)  push_back(a)
#define mk(a,b) make_pair(a,b)
#define dbg(x) cout << "now this num is " << x << endl;
#define met0(axx) memset(axx,0,sizeof(axx));
#define metf(axx) memset(axx,-1,sizeof(axx));
#define sd(ax) scanf("%d",&ax)
#define sld(ax) scanf("%lld",&ax)
#define sldd(ax,bx) scanf("%lld %lld",&ax,&bx)
#define sdd(ax,bx) scanf("%d %d",&ax,&bx)
#define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx)
#define sfd(ax) scanf("%lf",&ax)
#define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx)
#define pr(a) printf("%d\n",a)
#define plr(a) printf("%lld\n",a)
int ex,ey,sx,sy,sz,Minn = -1,ans,n,m;
string mp[1005];
int b[4][2] = {-1,0,1,0,0,1,0,-1},dis[1005][1005][4];
LL cnt[1005][1005][4];//到i,j位置时且朝向为z时的方案数.
map<char,int> mp1;
struct Node{int x,y,z;};
void init(){mp1['N'] = 0,mp1['S'] = 1,mp1['E'] = 2,mp1['W']  = 3;}
int check1(int z)//左转
{
 if(z == 0) return 3;
 if(z == 1) return 2;
 if(z == 2) return 0;
 if(z == 3) return 1;
}
int check2(int z)//右转
{
 if(z == 0) return 2;
 if(z == 1) return 3;
 if(z == 2) return 1;
 if(z == 3) return 0;
}
void bfs(int x,int y,int z)
{
 Node p;
 queue<Node> Q;
 p.x = x,p.y = y,p.z = z;
 dis[x][y][z] = 0;cnt[x][y][z] = 1;
 Q.push(p);
 while(!Q.empty())
 {
  Node q = Q.front();Q.pop();
  int px = q.x,py = q.y,pz = check1(q.z);//左转
  if(dis[px][py][pz] == -1)//第一次走到这种状态时,更新这种状态的最短路径
  {
   dis[px][py][pz] = dis[q.x][q.y][q.z]+1;
   cnt[px][py][pz] = (cnt[px][py][pz]+cnt[q.x][q.y][q.z])%Mod;
   p.x = px,p.y = py,p.z = pz;
   Q.push(p);
  }
  else if(dis[q.x][q.y][q.z]+1 == dis[px][py][pz]) cnt[px][py][pz] = (cnt[px][py][pz]+cnt[q.x][q.y][q.z])%Mod;
  px = q.x,py = q.y,pz = check2(q.z);//右转
  if(dis[px][py][pz] == -1)
  {
   dis[px][py][pz] = dis[q.x][q.y][q.z]+1;
   cnt[px][py][pz] = (cnt[px][py][pz]+cnt[q.x][q.y][q.z])%Mod;
   p.x = px,p.y = py,p.z = pz;
   Q.push(p);
  }
  else if(dis[q.x][q.y][q.z]+1 == dis[px][py][pz]) cnt[px][py][pz] = (cnt[px][py][pz]+cnt[q.x][q.y][q.z])%Mod;
  for(int k=1;;k++)
  {
   px = q.x+k*b[q.z][0],py = q.y+k*b[q.z][1],pz = q.z;
   if(px >= 0 && px < n && py >= 0 && py < m && mp[px][py] != '*')
   {
    if(dis[px][py][pz] == -1)
    {
     dis[px][py][pz] = dis[q.x][q.y][q.z]+1;
     cnt[px][py][pz] = (cnt[px][py][pz]+cnt[q.x][q.y][q.z])%Mod;
     p.x = px,p.y = py,p.z = pz;
     Q.push(p);
    }
    else if(dis[q.x][q.y][q.z]+1 == dis[px][py][pz]) cnt[px][py][pz] = (cnt[px][py][pz]+cnt[q.x][q.y][q.z])%Mod;
   }
   else break;//当遇到不能走时,或者走到边界时退出.
  }
 }
 for(int i=0;i<4;++i) if(dis[ex][ey][i] != -1) ans = min(ans,dis[ex][ey][i]);
 if(ans == INF) printf("0 0\n");
 else
 {
  LL temp = 0;
  for(int i=0;i<4;++i) if(dis[ex][ey][i] == ans) temp = (temp+cnt[ex][ey][i])%Mod;
  printf("%d %lld\n",ans,temp);
 }
}
int main()
{
 init();
 while(~sdd(n,m),n||m)
 {
  metf(dis);met0(cnt);ans = INF;
  for(int i=0;i<n;++i) cin >> mp[i];
  for(int i=0;i<n;++i)
  {
   for(int j=0;j<m;++j)
   {
    if(mp[i][j] != '*' && mp[i][j] != 'X' && mp[i][j] != '.') sx = i,sy = j,sz = mp1[mp[i][j]];
    if(mp[i][j] == 'X') ex = i,ey = j;
   }
  }
  bfs(sx,sy,sz);
 }
 system("pause");
 return 0;
}
标题“51单片机通过MPU6050-DMP获取姿态角例程”解析 “51单片机通过MPU6050-DMP获取姿态角例程”是一个基于51系列单片机(一种常见的8位微控制器)的程序示例,用于读取MPU6050传感器的数据,并通过其内置的数字运动处理器(DMP)计算设备的姿态角(如倾斜角度、旋转角度等)。MPU6050是一款集成三轴加速度计和三轴陀螺仪的六自由度传感器,广泛应用于运动控制和姿态检测领域。该例程利用MPU6050的DMP功能,由DMP处理复杂的运动学算法,例如姿态融合,将加速度计和陀螺仪的数据进行整合,从而提供稳定且实时的姿态估计,减轻主控MCU的计算负担。最终,姿态角数据通过LCD1602显示屏以字符形式可视化展示,为用户提供直观的反馈。 从标签“51单片机 6050”可知,该项目主要涉及51单片机和MPU6050传感器这两个关键硬件组件。51单片机基于8051内核,因编程简单、成本低而被广泛应用;MPU6050作为惯性测量单元(IMU),可测量设备的线性和角速度。文件名“51-DMP-NET”可能表示这是一个与51单片机及DMP相关的网络资源或代码库,其中可能包含C语言等适合51单片机的编程语言的源代码、配置文件、用户手册、示例程序,以及可能的调试工具或IDE项目文件。 实现该项目需以下步骤:首先是硬件连接,将51单片机与MPU6050通过I2C接口正确连接,同时将LCD1602连接到51单片机的串行数据线和控制线上;接着是初始化设置,配置51单片机的I/O端口,初始化I2C通信协议,设置MPU6050的工作模式和数据输出速率;然后是DMP配置,启用MPU6050的DMP功能,加载预编译的DMP固件,并设置DMP输出数据的中断;之后是数据读取,通过中断服务程序从DMP接收姿态角数据,数据通常以四元数或欧拉角形式呈现;再接着是数据显示,将姿态角数据转换为可读的度数格
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值