You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C++子集和程序输出异常,疑全局函数中for/while循环失效

问题分析与修复方案

你的程序的核心漏洞不是anshelp函数的循环逻辑,而是在main函数中错误地修改了numOfNotes变量的值,导致传入ans函数的参数变成了0,完全破坏了后续的子集遍历逻辑。

具体错误点

main函数中的这段代码:

cin>>numOfNotes>>money;
int denomination[numOfNotes];
int i=0;
while(numOfNotes){
    cin>>denomination[i];
    i++;
    numOfNotes--; // 这里把numOfNotes减到0了!
}
testCases--;
ans(numOfNotes,money,denomination)==1?cout<<"Yes"<<endl:cout<<"No"<<endl;

当你读取完所有纸币面额后,numOfNotes已经被循环减到了0。此时调用ans(numOfNotes, money, denomination),传入的第一个参数是0,ans函数里的循环条件i < (1 << numOfNotes)就变成了i < 1,只会执行一次i=0的情况——而help(0, ...)返回的肯定是0(因为没有选中任何子集),所以程序输出No

修复方法

你需要保留原始的纸币数量,不要修改numOfNotes变量,改用一个临时变量来控制循环:

cin>>numOfNotes>>money;
int denomination[numOfNotes];
int i=0;
int temp = numOfNotes; // 用临时变量代替原变量
while(temp){
    cin>>denomination[i];
    i++;
    temp--;
}
testCases--;
ans(numOfNotes,money,denomination)==1?cout<<"Yes"<<endl:cout<<"No"<<endl;

其他值得优化的点

  1. 避免非标准变长数组:C++标准并不支持int denomination[numOfNotes]这种变长数组(部分编译器如GCC支持作为扩展),建议改用std::vector<int>来存储面额,更安全且符合标准:
    vector<int> denomination(numOfNotes);
    for(int i=0; i<numOfNotes; i++){
        cin>>denomination[i];
    }
    
  2. help函数的逻辑可以简化:不需要单独写一个函数,直接在ans函数里计算当前掩码对应的子集和,减少函数调用开销:
    int ans(int numOfNotes,int money,int denomination[]){
        for(int i=0;i<(1<<numOfNotes);i++){
            int sum = 0;
            for(int j=0;j<numOfNotes;j++){
                if(i & (1<<j)){
                    sum += denomination[j];
                }
            }
            if(sum == money) return 1;
        }
        return 0;
    }
    
  3. 变量命名更清晰:比如help函数的i参数可以改成mask,更直观地表示它是子集的二进制掩码。

测试验证

修复后,输入测试用例1 3 3 1 1 1,程序会正确遍历所有8种子集组合,找到和为3的子集(三个1全选),输出Yes

内容的提问来源于stack exchange,提问作者Akshat Singh

火山引擎 最新活动