关于模拟退火
  • 板块学术版
  • 楼主ARIS1_0
  • 当前回复1
  • 已保存回复1
  • 发布时间2023/10/14 16:52
  • 上次更新2023/11/2 13:53:03
查看原帖
关于模拟退火
846661
ARIS1_0楼主2023/10/14 16:52

题意

现有 nn 个糖果,每个糖果有两个数值为美味度 aia_i 和美观度 bib_i。现要拿出不超过 ⌊n/2⌋+1\lfloor n/2 \rfloor + 1 个糖果使得它们的美味度和以及美观度大于所有糖果美味度的和以及美观度的和的二分之一,输出所取的编号,顺序任意。若无解,输出 -1。

其中:

1≤n≤1051\le n \le 10^5,ai,bi≤109a_i,b_i \le 10^9

我已经使用贪心算法 AC 此题,赛时我的退火骗了 7070 分,后来我骗到了 9393 分,只差一个点就过,我已经调参无数,卡常到底,现来求助是否可以从退火本身下手,优化复杂度

主函数代码:

ll n,sum1,sum2,nowmei,nowlook,ansmei,anslook;
struct node{
    ll mei,look,num;//美味度,美观度及编号
}a[100005],b[50005];//B数组作为答案数组,只需要开到 n 的一半即可。
//省略主函数定义
srand(time(0));
    n=read();
    for(int i=1;i<=n;++i){
        a[i].mei=read();
        a[i].num=i;
        sum1+=a[i].mei;
    }
    for(int i=1;i<=n;++i){
        a[i].look=read();
        sum2+=a[i].look;
    }//输入同时处理出整体上的美味度和以及美观度和
    SA();
    if(ansmei*2<sum1||anslook*2<sum2){
        puts("-1");
        return 0;
    }//若我们发现最优状态任无法满足,输出无解
    write(n/2+1);putchar('\n');
    for(int i=1;i<=n/2+1;i++){
        write(b[i].num);putchar(' ');
    }//输出编号

退火代码:

map<ll,ll>mp;//用来标记已经被选取的下标
const double delta=0.997;
void SA(){
    double T=1e4;//此题无需最优解,温度按喜好定
    while(T>1e-3){
        mp.clear();
        nowmei=0,nowlook=0;//循环不清空,_____
        ll lastmei=ansmei;//储存上一个解
        ll lastlook=anslook;
        memset(b,0,sizeof(b));
        for(int i=1;i<=n/2+1;i++){
            ll lucky=rand()%n+1;//选取随机数
            while(true){
                lucky=rand()%n+1;
                if(!mp[lucky]&&lucky<=n&&lucky>0)break;
            }//防止随机数发生重复与越界
            mp[lucky]++;//标记已选取的下标
            b[i]=a[lucky];//进行拷贝
            nowmei+=b[i].mei;//进行和的累加
            nowlook+=b[i].look;
        }
        int de1=nowmei-lastmei;//计算能量差
        int de2=nowlook-lastlook;
        if(de1>0||de2>0){
            ansmei=nowmei;
            anslook=nowlook;
            if(ansmei*2>sum1&&anslook*2>sum2)return;//若新解满足要求,直接退出
        }else{
            if(exp((-de1-de2)/T)-RAND_MAX>rand()){
                ansmei=nowmei;
                anslook=nowlook;
            }
        }
        T*=delta;
    }
}
2023/10/14 16:52
加载中...