一个简单的C++循环问题

今天看题解的时候看到一句话:

for(int i=head[x]; ~i; i=ne[i])

这里面中的“~i”,是什么意思呢?

~i表示对i的二进制按位取反,它在这个循环中作为结束条件,应该是表示当i的二级制按位取反后为0,则退出循环。

测试代码如下:

参考链接:


C语言中格式输出二进制的两种方法_c语言打印二进制_IT狼~的博客-CSDN博客 1.前言在我们日常的编程中,有时候需要格式化输出一个整形数据的二进制,但是在我们C语言中只有输出十进制:%d;输出十六进制:%x;输出单个字符:%c;输出字符串:%s,输出变量所在的地址:%p。而并没有这种二进制对应的格式,所以需要我们手动来实现。2.源码实现本篇博客给大家介绍两种方法:1.通过库函数itoa,需要包含头文件:#include ;2.通过十进制转成二进制的常用方法——短除法;为方便大家使用,将两种方法都封装成了函数,源码如下:#include &_c语言打印二进制 https://blog.csdn.net/weixin_46582567/article/details/124598001

 
#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;
    
} 
 

  • img

~i 是一个约定俗成的表示方法,用于表示负数。在循环条件中使用 ~i 可以简洁地表示 i != -1。
所以代码可以理解为:
初始化 i 为 head[x],表示从链表或数组中的 x 节点开始遍历。
循环条件为 i != -1,即当 i 不等于 -1 时继续循环。
每次循环结束后,更新 i 为 ne[i],即将下一个节点的索引赋值给 i,用于下一次循环。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这篇博客: 2022年江西理工大学软件工程学院程序设计竞赛C++题解中的 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;
    }
    
  • 以下回答来自chatgpt:

    "~i"是位求反运算符,也称为按位取反运算符。它将i的所有二进制位取反,即将0变为1,将1变为0。在C++中,整数类型会以补码的形式进行存储,因此取反运算会对数值进行求反加一的操作。

    具体来说,如果i的二进制表示为"0110",那么"~i"的结果为"1001"。

    在循环中使用"~i"可能是为了生成一个不同于i的索引值或标识符。根据具体的上下文和代码逻辑,可以进一步判断代码段中"~i"的用途和意义。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^