• 【转载】随机化贪心


    随机化贪心,顾名思义,就是边随机边贪心

    这类算法适合解决动态规划类的题目

    思想:在贪心原则正确的情况下,随机执行足够多次,就是正解了(涉及到概率学,这里不深究)

    不要以为随机到正解几率很小,假设随机到正解的概率为0.1%,我们执行100000次贪心,每次取最优,得到正解的概率是100%

    也就是这种贪心也变成了某种意义上的正解

    至于例子嘛..

    有N(3≤N≤40)块木板,每块的长度Li(1≤Li≤40)都是整数,利用所有的木板围成一个三角形使得面积最大。  

    计算出这个最大的面积。  

    输入格式:  

    第1行:一个整数N  

    第2..N+1行:每行包含一个整数,即是木板长度。  

    输出格式:  

    仅一个整数:最大面积乘以100然后舍尾的结果。如果无法构建,输出-1。 

    样例输入:  5  1  1  3  3  4 

    样例输出:  

    692 

    我们考虑贪心,贪心原则不难想到,我们尽量让三边的差小,他的面积就大

    所以每次将木板加入当前的最短边即可完成贪心

    附上随机化贪心代码和测试详情

     1     #include <iostream>  
     2     #include <cstdio>  
     3     #include <cmath>  
     4     #include <cstdlib>  
     5     using namespace std;  
     6     int n,a[41],ans=-1;  
     7     void wash()//随机洗木板顺序  
     8     {  
     9         for(int i=1;i<=n;i++)  
    10         {  
    11             int t=rand()%n;  
    12             a[0]=a[t];  
    13             a[t]=a[i];  
    14             a[i]=a[0];  
    15         }  
    16     }  
    17     int hl(double aa,double bb,double cc)//海伦公式求面积  
    18     {  
    19         if(aa+bb>cc&&bb+cc>aa&&aa+cc>bb)  
    20         {  
    21             double p=(aa+bb+cc)/2;  
    22             return trunc(sqrt(p*(p-aa)*(p-bb)*(p-cc))*100);  
    23         }  
    24         else return -1;  
    25     }  
    26     void work()//贪心程序  
    27     {  
    28         int p[3],pos;  
    29         p[0]=a[1];p[1]=a[2];p[2]=a[3];  
    30         for(int i=4;i<=n;i++)  
    31         {  
    32             int min=0x7fffffff;  
    33             for(int j=0;j<=2;j++)  
    34             {  
    35                   
    36                 if(min>p[j])  
    37                 {  
    38                     min=p[j];  
    39                     pos=j;  
    40                 }  
    41             }  
    42             p[pos]+=a[i];  
    43         }  
    44         ans=max(ans,hl(p[0],p[1],p[2]));  
    45     }  
    46     int main()  
    47     {  
    48         scanf("%d",&n);  
    49         for(int i=1;i<=n;i++)  
    50         scanf("%d",&a[i]);  
    51         for(int i=1;i<=10000;i++)  
    52         {  
    53             wash();  
    54             work();   
    55         }  
    56           
    57         printf("%d
    ",ans);  
    58         return 0;  
    59     }   

    一共提交30遍(为了测试概率),AC 30遍

    测试点 #1通过该测试点。 得分9,耗时0ms,内存2052kB。
    测试点 #2通过该测试点。 得分9,耗时0ms,内存2052kB。
    测试点 #3通过该测试点。 得分9,耗时0ms,内存2052kB。
    测试点 #4通过该测试点。 得分9,耗时0ms,内存2048kB。
    测试点 #5通过该测试点。 得分9,耗时15ms,内存2052kB。
    测试点 #6通过该测试点。 得分9,耗时15ms,内存2052kB。
    测试点 #7通过该测试点。 得分9,耗时15ms,内存2052kB。
    测试点 #8通过该测试点。 得分9,耗时15ms,内存2052kB。
    测试点 #9通过该测试点。 得分9,耗时15ms,内存2052kB。
    测试点 #10通过该测试点。 得分9,耗时15ms,内存2052kB。
    测试点 #11通过该测试点。 得分10,耗时31ms,内存2048kB。

    实验证明,这是完美的骗分,足足骗了100分。。

  • 相关阅读:
    守护进程的创建(syslog函数)
    进程控制fork vfork,父子进程,vfork保证子进程先运行
    进程概述,父子进程
    gdb调试分析多线程死锁
    tcp握手
    实现自己的ls命令
    获取当前目录getcwd,设置工作目录chdir,获取目录信息
    目录的创建,删除,获取当前目录
    文件的移动,删除 rename remove unlink 函数
    sendkeys
  • 原文地址:https://www.cnblogs.com/luv-letters/p/9188584.html
Copyright © 2020-2023  润新知