随机化算法
随机化算法是这样一种算法,在算法中使用了随机函数,且随机函数的返回值直接或者间接的影响了算法的执行流程或执行结果。随机化算法基于随机方法,依赖于概率大小。
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;
}
贪心+随机化
题意: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;
}