PAT 甲级 1053 测试点5

在写这道题的时候出现了测试点5未通过的情况,以下是初次尝试的代码,写的有些啰嗦,反正主要用了dfs的方法写的。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct leaf{
    vector<int>path;
};
vector<leaf> leafs;
int path[105]={0},n,m,s,k,temp,id;
long long weight[105]={0} ;
vector<int> son[105];
bool cmp(leaf a,leaf b){//发生段错误或运行时错误,这里出问题了
    for(int i=0;i<a.path.size() && i<b.path.size();i++){
        if(a.path[i]!=b.path[i])return a.path[i]>b.path[i];
    }
    // return a.path.size()>b.path.size();//为什么?//这不管是什么都可以通过
    // return true;
}
void dfs(int index,int high,long long sum){
    path[high-1]=weight[index];
    if(sum>s)return ;
    if(son[index].size()==0){
        if(sum!=s)return ;
        leaf l;
        for(int i=0;i<high;i++){
            l.path.push_back(path[i]);
        }
        leafs.push_back(l);
        return ;
    }
    for(int i=0;i<son[index].size();i++){
        dfs(son[index][i],high+1,sum+weight[son[index][i]]);
    }
}
int main(){
    cin>>n>>m>>s;
    for(int i=0;i<n;i++) cin>>weight[i];
    for(int i=0;i<m;i++){
        cin>>id>>k;
        for(int j=0;j<k;j++){
            cin>>temp;
            son[id].push_back(temp);
        }
    }
    dfs(0,1,weight[0]);
    sort(leafs.begin(),leafs.end(),cmp);
    for(int i=0;i<leafs.size();i++){
        for(int j=0;j<leafs[i].path.size();j++){
            if(j!=0)printf(" ");
            printf("%d",leafs[i].path[j]);
        }
        printf("\n");
    }
    return 0;
}

然后找了很久发现是cmp比较函数出了问题,当leafs中所有元素都相同时就会报错,以下是模拟测试点5的输入:(其实只要leafs数组中超过17个相等的元素就会报错了)

20 1 20
10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
00 19 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

接着我找到了一篇文章,讲的是为什么自建的cmp函数放到sort函数会报错的原因:

C++中使用std::sort自定义排序规则时要注意的崩溃问题_std::sort 崩溃-优快云博客

简而言之说的就是如果cmp(a,b)==true 那么一定要cmp(b,a)==false;

而cmp(a,b)==false 且cmp(b,a)==false 的情况也是可以的;

但是 cmp(a,b)==true 且 cmp(b,a)==true 的情况是错误的。

原理是sort函数中有一段__unguarded_linear_insert的函数只有当cmp(a,a+1)==false 时才停下来。

所以正确的改动很简单,在cmp里面最后加上return false;就可以了(一定不能return true;!!!)

以下是ac的代码(就改动一个点就不用看啦)

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct leaf{
    vector<int>path;
};
vector<leaf> leafs;
int path[105]={0},n,m,s,k,temp,id;
long long weight[105]={0} ;
vector<int> son[105];
bool cmp(leaf a,leaf b){
    for(int i=0;i<a.path.size() && i<b.path.size();i++){
        if(a.path[i]!=b.path[i]){
            return a.path[i]>b.path[i];
        }
    }
    return false;
}
void dfs(int index,int high,long long sum){
    path[high-1]=weight[index];
    if(sum>s)return ;
    if(son[index].size()==0){
        if(sum!=s)return ;
        leaf l;
        for(int i=0;i<high;i++){
            l.path.push_back(path[i]);
        }
        leafs.push_back(l);
        return ;
    }
    for(int i=0;i<son[index].size();i++){
        dfs(son[index][i],high+1,sum+weight[son[index][i]]);
    }
}
int main(){
    cin>>n>>m>>s;
    for(int i=0;i<n;i++) cin>>weight[i];
    for(int i=0;i<m;i++){
        cin>>id>>k;
        for(int j=0;j<k;j++){
            cin>>temp;
            son[id].push_back(temp);
        }
    }
    dfs(0,1,weight[0]);
    sort(leafs.begin(),leafs.end(),cmp);
    for(int i=0;i<leafs.size();i++){
        for(int j=0;j<leafs[i].path.size();j++){
            if(j!=0)printf(" ");
            printf("%d",leafs[i].path[j]);
        }
        printf("\n");
    }
    return 0;
}

之后再碰到所有元素相同的情况要记得cmp函数在cmp(a,a)的时候返回false就可以了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值