• 题解 洛谷 P4044 【[AHOI2014/JSOI2014]保龄球】


    (DP) 来做的话会很麻烦,细节会很多,考虑乱搞一些的做法。(n) 很小,答案和排列顺序有关,所以考虑模拟退火来解决本题。

    产生新状态即为交换当前排列的两个位置。调参时可以采取降低退火次数,升高温度和降温系数来处理,这样正确性会高。

    #include<bits/stdc++.h>
    #define maxn 55
    #define eps 1e-10
    using namespace std;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int n,m,ans,cnt=1000;
    struct node
    {
        int a,b;
    }p[maxn];
    int calc()
    {
        int v=0;
        for(int i=1;i<=n+m;++i)
        {
            v+=p[i].a+p[i].b;
            if(p[i-1].a==10) v+=p[i].a+p[i].b;
            else if(p[i-1].a+p[i-1].b==10) v+=p[i].a;
        }
        return v;
    }
    void SA()
    {
        double T=1000000,delta=0.9895;
    	while(T>eps)
    	{
    		int x=rand()%(n+m)+1,y=rand()%(n+m)+1,v;
            while(x==y||(m&&(x==n||y==n))) x=rand()%(n+m)+1,y=rand()%(n+m)+1;
    		swap(p[x],p[y]),v=calc();
    		if(v>ans) ans=v;
    		else if(exp((v-ans)/T)*RAND_MAX<rand()) swap(p[x],p[y]);
    		T*=delta;
    	}
    }
    int main()
    {
        srand((long long)new char),read(n);
        for(int i=1;i<=n;++i) read(p[i].a),read(p[i].b);
        if(p[n].a==10) m=1,read(p[n+1].a),read(p[n+1].b);
        while(cnt--) SA();
        printf("%d",ans);
        return 0;
    }
    
  • 相关阅读:
    向日葵、阳光
    laravel还是给我太多惊喜了
    滴滴笔试题——小试牛刀
    剑指offer——二叉搜索树的后序遍历序列
    2019春招美团笔试
    首次实习生招聘会——航天一院
    有趣的数字
    剑指offer——从上往下打印二叉树
    剑指offer——栈的压入、弹出序列
    剑指offer——包含min函数的栈
  • 原文地址:https://www.cnblogs.com/lhm-/p/13520115.html
Copyright © 2020-2023  润新知