CF 906B - Seating of Students 随机 乱搞 技巧

题意:

给你一个N * M 的表,第i行j列的数是 (i - 1) * m + j,现在要重新安排数的位置,问你有没有一种方案使得原来相邻的数现在不相邻。

题解:

随机乱搞。

给了两秒,我们设置程序执行了1.9秒时退出随机,输出NO。

while (clock() < 1.9 * CLOCKS_PER_SEC)

一开始直接用random_suffle,暴力判断当前是否可行,如果不可行就continue。但这样搜索正解太慢,wa了。

然后我想,每次random_suffle之后都要O(n * m)判断, 如果当前只差了几个数位置不对,没必要重新random_suffle。

如果当前位置不可行,那么我们继续和后面的位置rand() 100次交换,如果还是不行,那再 random_shuffle。

然后就A了。。。

至于为什么可以随机搞,大概因为答案很多吧,要搜索到还是很容易的。

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <bitset>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <cmath>
#include <ctime>
#ifdef LOCAL
#define debug(x) cout<<#x<<" = "<<(x)<<endl;
#else
#define debug(x) 1;
#endif

#define chmax(x,y) x=max(x,y)
#define chmin(x,y) x=min(x,y)
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
#define lowbit(x) x&-x
#define mp make_pair
#define pb push_back
#define fir first
#define sec second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, int> pii;

const ll MOD = 1e9 + 7;
const double eps = 1e-10;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 1e6 + 5;

int a[MAXN];
int n, m;

int check (int i) {
    if (i % m != 0) if (abs (a[i] - a[i - 1]) == 1 || abs (a[i] - a[i - 1]) == m) return true;
    if (i >= m) if (abs (a[i] - a[i - m]) == 1 || abs (a[i] - a[i - m]) == m) return true;
    return 0;
}


int main() {
#ifdef LOCAL
    freopen ("input.txt", "r", stdin);
#endif
    scanf ("%d %d", &n, &m);
    for (int i = 0; i < n * m; i++) a[i] = i + 1;
    int ok = 0;
    while (clock() < 1.9 * CLOCKS_PER_SEC) {
        random_shuffle (a, a + n * m);
        int f = 0;
        for (int i = 0; i < n * m; i++) {
            int cnt = 0;
            while (check (i) && cnt <= 100) {
                if (i < n * m - 1) swap (a[i], a[rand() % (n * m - i - 1) + i + 1]);
                else cnt = INF;
                cnt++;
            }
            if (cnt > 100) {
                f = 1;
                break;
            }
        }
        if (f) continue;
        ok = 1;
        puts ("YES");
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < m; j++)
                printf ("%d ", a[ (i - 1) * m + j]);
            puts ("");
        }
        break;
    }
    if (!ok) puts ("NO");
    return 0;
}

 

猜你喜欢

转载自blog.csdn.net/c6376315qqso/article/details/82777671