随机化算法

随机化算法

随机化算法是这样一种算法,在算法中使用了随机函数,且随机函数的返回值直接或者间接的影响了算法的执行流程或执行结果。随机化算法基于随机方法,依赖于概率大小。

POJ 3318 Matrix Multiplication

题意:给出三个n*n矩阵A,B,C,n<=500 判断A*B=C?

矩阵乘法直接做O(N^3) TLE
若AB=C 必有矩阵H使得 HAB=HC 令H为1*N的行向量,则复杂度降为O(n^2) 

反之AB!=C 也可能存在 HAB=HC,所以将H随机化 每个H都要满足 

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring> 
using namespace std;
typedef long long ll;
const int N=2e3+20;
const ll M=2e9;
ll n,a[N][N],b[N][N],c[N][N],h[2][N],t1[2][N],t2[2][N],t3[2][N];
int main()
{
	while(cin>>n)
	{
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				scanf("%I64d",&a[i][j]);
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				scanf("%I64d",&b[i][j]);
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				scanf("%I64d",&c[i][j]);
	
		//随机50个H
		bool ans=true;
		for(int l=1;l<=20;l++)
		{
			memset(t1,0,sizeof(t1));
			memset(t2,0,sizeof(t2));
			memset(t3,0,sizeof(t3));
			bool flag=true;
			for(int i=1;i<=n;i++)
				h[1][i]=rand()%M+1;
			for(int i=1;i<=n;i++)
				for(int j=1;j<=n;j++)
					t1[1][i]=t1[1][i]+h[1][j]*a[j][i];	 
			for(int i=1;i<=n;i++)
				for(int j=1;j<=n;j++)
					t2[1][i]=t2[1][i]+t1[1][j]*b[j][i];
		
			for(int i=1;i<=n;i++)
				for(int j=1;j<=n;j++)
					t3[1][i]=t3[1][i]+h[1][j]*c[j][i];
			
			for(int i=1;i<=n;i++)
			{
			//	cout<<t2[1][i]<<' '<<t3[1][i]<<endl;
				if(t2[1][i]!=t3[1][i])
				{
					
					flag=false;
					break;
				}
			}
			if(flag==false)
			{
				ans=false;
				break;	
			}	
		} 
		if(ans)
			puts("YES");
		else
			puts("NO");
	
	}
	return 0;
}

POJ 2454 Jersey Politics

贪心+随机化

题意:3*K个city K<=60,分成3份 要求至少有两份满足 每份的和>500*K,一定有解,求分的方案?
从小->大排序 因为一定有解 满足的两份,最优为包含后2*K个元素,
另A=[k+1..2k],B=[2k+1..3K] 若A或者B不满足 则从B或者A随机交换一个过去  K<=60 数据较小 正常情况下都可以很快随机到答案 

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring> 
using namespace std;
typedef long long ll;
const int N=2e3+20;
struct node{
	int x,id;
}a[N];
int k;
bool cmp(node a,node b)
{
	return a.x<b.x;
}
node A[N],B[N];
bool check()
{
	int s=500*k,s1=0,s2=0;
	for(int i=1;i<=k;i++)
		s1+=A[i].x,s2+=B[i].x;
	return s1>s&&s2>s;
}
int main()
{
	while(cin>>k)
	{
		for(int i=1;i<=3*k;i++)
		{
			cin>>a[i].x;
			a[i].id=i;
		}
		sort(a+1,a+1+3*k,cmp);
		for(int i=1;i<=k;i++)
			A[i]=a[k+i],B[i]=a[2*k+i];
		while(true)
		{
			if(check())
				break;
			int i=rand()%k+1;//随机交换 
			int j=rand()%k+1;
			swap(A[i],B[j]);
		}
		for(int i=1;i<=k;i++)
			cout<<a[i].id<<endl;
		for(int i=1;i<=k;i++)
			cout<<A[i].id<<endl;
		for(int i=1;i<=k;i++)
			cout<<B[i].id<<endl;
	}
	return 0;
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值