zoukankan      html  css  js  c++  java
  • 【洛谷P4212】外太空旅行【随机】【贪心】

    题目大意:

    题目链接:https://www.luogu.org/problemnew/show/P4212
    给出nn个人的关系,两个人不是朋友就是敌人。选择其中的kk个人,使得这kk个人都是朋友关系。求kk的最大值。


    思路:

    好的下面为大家带来一道状压DP50分DFS70分随机+贪心AC的题目(逃
    n50n\leq50,状压和DFS都得跑T。
    正解如下:

    1. 首先,你打了一个DFS想骗骗分,还拿了70分。
    2. 然后,你想到DFS都能拿70,就信心满满地去打了一个DP,结果只拿了50
    3. 于是你在DFS上乱加优化,成功优化到了90,但是最后一个点死活就是卡不过。
    4. 于是,无奈和愤怒交加的你点开了标签。。。
    5. 然后你就想到。。。在这里插入图片描述

    正解:

    正解是随机+贪心。
    可以随机一个序列,表示选人进入集合的序列。
    然后就按照枚举的序列开始贪心。如果这个人能进入集合(与集合里的所有人都是朋友关系),那么就将他进入集合,否则不进。
    然后就可以得出在这个序列的情况下的进入集合的人数。那么多次随机数列,并将每次的答案都进行比较,最后输出这几个答案的最优值即可。
    由于可以随机5000050000(甚至更多)次,所以答案基本就出来了。偶尔WA了就将随机次数开大即可。


    代码:

    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    const int N=50000; 
    int n,a[61],x,y,ans,sum;
    bool f[61][61],p[61];
    
    int main()
    {
    	scanf("%d",&n);
    	while (scanf("%d%d",&x,&y)==2)
    	{
    		f[x][y]=true;
    		f[y][x]=true;
    	}
    	srand((unsigned long long)new char);  //随机种子
    	for (int k=1;k<=N;k++)
    	{
    		memset(p,0,sizeof(p));
    		for (int i=1;i<=n;i++)  //随机一个数列
    		{
    			while ((x=rand()%n+1)&&(p[x])) ;
    			a[i]=x;
    			p[x]=true;
    		}
    		memset(p,0,sizeof(p));
    		sum=0;
    		for (int i=1;i<=n;i++)
    		{
    			if (!p[a[i]])  //可以进入集合
    			{
    				sum++;
    				for (int j=1;j<=n;j++)
    				 if (!f[a[i]][j]) p[j]=true;  //将他的敌人标记
    			}
    		}
    		ans=max(ans,sum);
    	}
    	printf("%d\n",ans);
    	return 0;
    }
    
  • 相关阅读:
    小程序查看导航
    PHP计算两个坐标之间的距离
    微信小程序获取位置
    小程序重置index,重置item
    nmap使用教程
    boost checked_delete提升安全性
    转: 带你玩转Visual Studio——带你理解多字节编码与Unicode码
    visual studio 开发linux程序
    stl 比较和boost LessThanComparable
    c++11 auto unique_ptr 等
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998578.html
Copyright © 2011-2022 走看看