参考文档:
https://blog.csdn.net/caimouse/article/details/55668071 (mt19937随机数)
https://blog.csdn.net/sr_19930829/article/details/38236769 (POJ 3318)
随机化算法即随机生成因子,利用其随机生成数结合题目条件对所给数据进行校验。
需要保证前提:
1.有明确的正确数据以供校验
2.随机化的次数必须要足够多以保证所有数据得到验证以保障准确性
例题
1.Matrix Multiplication(POJ 3318)
http://poj.org/problem?id=3318
题目大意:给定三个矩阵问其中C矩阵是否是给定的A和B矩阵相乘得到的矩阵。
题目本身给了hint:O(N^3)会TLE
因此该题可以使用随机化方法验证给定数据以判断是否正确。
AC代码如下:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <string>
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <vector>
#include <set>
#include <queue>
#include <iomanip>
#include <time.h>
using namespace std;
typedef long long ll;
const int maxn = 500 + 5;
int a[maxn][maxn];
int b[maxn][maxn];
int c[maxn][maxn];
int main(){
int n;
while(scanf("%d",&n)!=EOF) {
srand(time(NULL)); //随机化种子
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(c, 0, sizeof(c));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
scanf("%d", &a[i][j]);
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
scanf("%d", &b[i][j]);
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
scanf("%d", &c[i][j]);
}
}
bool f = 1;
for (int k = 1; k <= 30000; k++) {
int row = rand() % n + 1; //从1开始生成行
int col = rand() % n + 1; //从1开始生成列
int tmp = 0;
for (int i = 1; i <= n; i++)
tmp += (a[row][i] * b[i][col]);
if (tmp != c[row][col]) // 不符合要求
f = 0;
}
if (f) printf("YES\n");
else printf("NO\n");
}
return 0;
}
2.Hamming Distance(HDU 4712)
题目大意:两个二进制字符串之间任意两个值抑或值中的1的个数。
由题意可知该值只能在0~20,因此采取随机化探测。
读入字符串后任意选取(随机)的编号,(不能重复),进行计算并且每次取最小值。
AC代码:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <string>
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <vector>
#include <set>
#include <queue>
#include <iomanip>
#include <random>
#include <time.h>
using namespace std;
typedef long long ll;
const int maxn = 5e5 + 5;
int cal(int x) { //计算1的个数
int ans = 0;
while(x) {
ans += (x&1);
x>>=1;
}
return ans;
}
int num[maxn];
int main(){
int t;
scanf("%d",&t) ;
while(t--) {
srand(time(NULL)); //随机化种子
int tmp = 25; //保证足够大
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++) scanf("%X",&num[i]); //%X即十六进制数
for(int i = 0; i < 200000; i++) { //保证足够多
int j = rand() % n + 1;
int k = rand() % n + 1;
if (j == k) j = j % n + 1; //如果相等需要处理
tmp = min(tmp, cal(num[j] ^ num[k])); //进行计算
}
printf("%d\n",tmp);
}
return 0;
}