【转载】随机化贪心
随机化贪心,顾名思义,就是边随机边贪心
这类算法适合解决动态规划类的题目
思想:在贪心原则正确的情况下,随机执行足够多次,就是正解了(涉及到概率学,这里不深究)
不要以为随机到正解几率很小,假设随机到正解的概率为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\n",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分。。