今天看题解的时候看到一句话:
for(int i=head[x]; ~i; i=ne[i])
这里面中的“~i”,是什么意思呢?
~i表示对i的二进制按位取反,它在这个循环中作为结束条件,应该是表示当i的二级制按位取反后为0,则退出循环。
测试代码如下:
参考链接:
#include <stdio.h>
#include <stdlib.h>
int main(void){
int i = 2;
// https://blog.csdn.net/weixin_46582567/article/details/124598001
char bStr[33]={0};
itoa(i,bStr,2); // 将i转为对应的二进制字符串
int i2 = ~i;
char bStr2[33]={0};
itoa(i2,bStr2,2); // 将~i转为对应的二进制字符串
// https://blog.csdn.net/m0_65096921/article/details/125791768
// https://blog.csdn.net/qq_41705423/article/details/104648397/
// https://baike.baidu.com/item/printf/7467706?fr=ge_ala
// 打印i和~i及其对应的二进制串
printf("i=%d,\t二进制为:%032s\n",i,bStr);
printf("~i=%d,\t二进制为:%032s\n",i2,bStr2);
return 0;
}
~i 是一个约定俗成的表示方法,用于表示负数。在循环条件中使用 ~i 可以简洁地表示 i != -1。
所以代码可以理解为:
初始化 i 为 head[x],表示从链表或数组中的 x 节点开始遍历。
循环条件为 i != -1,即当 i 不等于 -1 时继续循环。
每次循环结束后,更新 i 为 ne[i],即将下一个节点的索引赋值给 i,用于下一次循环。
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
在电影中,陈末与幺鸡约定了要在稻城再见。
但是,陈末在快抵达稻城的时候,被一群可恶的神秘人抓走了,神秘人把陈末关在了一个没有出口的二维迷宫里。
上帝见陈末如此可怜,就给了陈末一张迷宫的地图,并告诉给陈末,只要陈末能到达迷宫的边界,上帝就会花1单位时间帮他逃出迷宫。
迷宫内有毒气,毒气在每个单位时间会向四周扩散(即向四个方向扩散一个单位),毒气无法扩散到墙上。
例如,毒气此时在(x , y),那么毒气会花1个单位时间 扩散到(x,y+1),(x+1,y),(x-1,y),(x,y-1),并在新的位置再次扩散,前提为目标点不是墙,且不在迷宫范围之外。
陈末在每个单位时间只能向一个方向前进一个单位,陈末翻不了这里的墙。
例如,陈末此时在(x,y),那么陈末可以花费1个单位时间走到 (x,y+1),(x+1,y),(x-1,y),(x,y-1)中的任意一个,前提为目标点不是墙,且不在迷宫范围之外。
请问,陈末至少要花多少时间才能逃出迷宫,如果陈末始终无法逃出迷宫请输出 “NO” (不包含双引号)
输入描述:
第一行两个整数n(1≤n≤103),m(1≤m≤103),分别表示二维迷宫的行数和列数。
下面有 n 行 ,每行 m 个字符,代表二维迷宫的地图。
*代表这个位置有毒气
#代表这个位置有墙
.代表这个位置是空地
C代表陈末在这个位置
保证地图只有以上4种字符,并且C保证只出现1次。
注意:不保证毒气只有一个位置具有。
输出描述:
陈末至少要花多少时间才能逃出迷宫,如果陈末始终无法逃出迷宫请输出 “NO” (不包含双引号)
示例1
输入:
3 3
*##
*C.
###
输出:
2
说明:
陈末可以花费1个单位时间从(2,2)到达(2,3),然后上帝就会花1个单位时间救他。
示例2
输入:
4 4
####
#C*#
#*…
###.
输出:
NO
说明:
很不幸,无论陈末走哪里,他都会被毒死。
解题思路
如果陈末到达x点的最短时间比毒气到达x点的最短时间长或者相等,那么就跑不掉。
因为毒气有多个起点
所以要先bfs求每个毒气到达每个点的最短距离,
再求陈末到达每个点的最短距离,作比较。
如果在边界,不是墙并且跑得掉,花费时间就是到达边界时间+1
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
const int M = 1e3+10;
int n,m;
char arr[N][M]; //存图
int cx,cy; //陈末起点
int duS[N][M],cmS[N][M]; //duS毒气到达点的时间,cmS陈末到达点的时间
int dx[] = {-1,0,1,0},dy[] = {0,1,0,-1};
typedef struct p_node{
int x,y;
}P;
queue<P> du,cm;
int main(){
cin>>n>>m;
for(int i = 1;i<=n;++i){
for(int j = 1;j<=m;++j){
cin>>arr[i][j];
duS[i][j] = cmS[i][j] = 1e9;
if(arr[i][j]=='C') cx=i,cy=j;
if(arr[i][j]=='*') du.push({i,j}),duS[i][j] = 0;
}
getchar();
}
//毒气到达时间
while(!du.empty()){
P u = du.front();
du.pop();
for(int i = 0;i<4;++i){
int xx = u.x+dx[i],yy = u.y+dy[i];
if(xx<1||xx>n||yy<1||yy>m) continue;
if(arr[xx][yy]=='#') continue;
if(duS[xx][yy]<=duS[u.x][u.y]+1) continue;
duS[xx][yy] = min(duS[xx][yy], duS[u.x][u.y]+1);
du.push({xx,yy});
}
}
//陈末到达时间
int ans = -1;
cm.push({cx,cy});
cmS[cx][cy]=0;
while(!cm.empty()){
P u = cm.front();
cm.pop();
if(u.x==1||u.y==1||u.x==n||u.y==m){
if(cmS[u.x][u.y]+1<=duS[u.x][u.y]){ //最先到达边界的点一定是时间最短的
ans = cmS[u.x][u.y]+1;
break;
}
}
for(int i = 0;i<4;++i){
int xx = u.x+dx[i],yy = u.y+dy[i];
if(xx<1||xx>n||yy<1||yy>m) continue;
if(cmS[xx][yy]<=cmS[u.x][u.y]+1) continue;
if(arr[xx][yy]=='.'&&cmS[xx][yy]>=cmS[u.x][u.y]+1){
cmS[xx][yy] = cmS[u.x][u.y]+1;
cm.push({xx,yy});
}
}
}
if(ans==-1) cout<<"NO"<<endl;
else cout<<ans<<endl;
return 0;
}
"~i"是位求反运算符,也称为按位取反运算符。它将i的所有二进制位取反,即将0变为1,将1变为0。在C++中,整数类型会以补码的形式进行存储,因此取反运算会对数值进行求反加一的操作。
具体来说,如果i的二进制表示为"0110",那么"~i"的结果为"1001"。
在循环中使用"~i"可能是为了生成一个不同于i的索引值或标识符。根据具体的上下文和代码逻辑,可以进一步判断代码段中"~i"的用途和意义。