机房水题欢乐赛 20160216

23 篇文章 0 订阅
19 篇文章 0 订阅

——暨校GDKOI集训赛

T1: 数字统计

给出N个正整数,其中有且只有有一个数字出现超过n/2次,求这个数字

Input

第一行为N,接下来一行,有N个正整数。

Output

出现n/2次的数字。

Sample Input

5
1 2 3 3 3

Sample Input

3

Hint

20%: n1000
40%: n10000
60%: n10000000
100%: n50000000,ai2147483647
经亲自查看数据得,最大的输入文件30M。

Solution

出题人怒调戏众人:标程只有10行!

于是因为数据水一堆人骗了接近满分让出题人颜面扫地
而且好像标程在本地测得40分,原因超时。。我开了快速读入只有60分。。
还是暴力大法好,哈希保平安!
显然只有 O(n) 的方法,考虑先置答案为第一个数字,然后扫一遍,如果 aiai1 ,那么 count++ ,否则 count ,如果 count=0 ,那么置答案为下一个数字即可。
然而标程怒跪并不贴程序。。

T2: 翻骰子

我们有2*n个骰子,分成两行放置(lz注:设为a和b两个向量)。有一种操作,是将上下两个骰子翻转过来(lz注:交换 ai,bi ),我们想知道,当第一行的和减去第二行的和(lz注:取绝对值)最小时,需要翻转的最小次数。

Input

第一行一个正整数n
接下来n行,每行两个整数,分别表示第i列的上下两个骰子的点数(lz注:即 1ai,bi6 )。

Output

一行一个整数,最少的翻转次数。

Sample Input

4
6 1
1 5
1 3
1 2

Sample Output

1

Sample Explanation

将最后一列的骰子翻转即可。

Hint

20%: n10
50%: n100
100%: n1000

Solution

考虑表示一下答案,

ans=|sumAsumB|

如果交换了第 i 列,那么
ans=|(sumAai+bi)(sumBbi+ai)|=|sumAsumB+2bi2ai|

x=sumAsumB,ci=2(aibi) ,那么
ans=xici

使ans最小,那么就选出来的某些 ci 的和尽可能地接近 x ,似乎是个背包问题?
搜索dp皆可解决之。

另外纯dp也可。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#define FOR(i,j,k) for(i=j;i<=k;i++)

const int N = 1005, Maxx = 10005, inf = 0x7f7f7f7f;

int i,j,k,a,b,n,tc=0;
int g[N], f[N][N];
int g0, ma, da = inf, D = inf;

void getmin(int &a, int b) { if (a > b) a = b; }

int main() {
    memset(f, 127, sizeof f);
    scanf("%d",&n);
    FOR(i,1,n) scanf("%d%d", &a, &b), g[i] = a - b;
    g0 = 5 * n; ma = n * 10;
    f[0][g0] = 0;
    int i, j;
    FOR(i,1,n) FOR(j,0,ma) if (f[i - 1][j] != inf) {
        getmin(f[i][j + g[i]], f[i - 1][j]);
        getmin(f[i][j - g[i]], f[i - 1][j] + 1);
    }
    FOR(j,0,ma) if (f[n][j] != inf)
        if (abs(j - g0) < D) {
            D = abs(j - g0);
            da = f[n][j];
        } else if (abs(j - g0) == D)
            getmin(da, f[n][j]);

    printf("%d",da);
    return 0;
}

T3: 糖果传递

详见:http://blog.csdn.net/huanghongxun/article/details/50675569

T4: N^2皇后问题

给定N,求N^2皇后问题的一组可行解。

Input

一个N(1\leq N\leq 8)

Output

N2行,每行一个整数,表示每行中的第几列放皇后。

Sample Input

1

Sample Output

1

Solution

说实话考试时没想到 n2 有啥神奇特征,于是自信写随机。。
好像机房有同学是dfs过的,因为发现大多数的皇后都是在上一行皇后的右边2格位置(一个马的距离),优选那个位置继续dfs,然后打表。好像这样dfs特别快。。
正解好神奇。。
发现实际上。。N^2皇后就相当于一个N皇后问题,然后在放了皇后的地方在开一个N*N的棋盘,小棋盘结果N皇后问题的解。因此问题转化为求N皇后问题的解。于是N^3,N^4以此类推。
只给随机的程序。。

#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;
#define FOR(i,j,k) for(i=j;i<=k;i++)
#define rep(i,j,k) for(i=j;i<k;i++)

int random(int x) {
    return (int)(((double) rand()) / RAND_MAX * x);
}

int c[8192], n;

void init() {
    int i, j;    
    rep(i,0,n) c[i] = i;
    rep(i,0,n) {
        j = random(n);
        swap(c[j], c[n-j-1]);
    }
}

int h(vector<int> &l) {
    int i, j;
    l.clear();
    rep(i,0,n) rep(j,i+1,n)
        if (c[j] == c[i] + j - i || c[j] == c[i] - j + i)
            l.push_back(j);
    return l.size();
}

int exc(int j1, int j2, vector<int> &l) {
    vector<int> nl;
    swap(c[j1], c[j2]);
    h(nl);
    if (nl.size() > l.size()) swap(c[j1], c[j2]);
    else l = nl;
    return nl.size();
}

int next(vector<int> &l) {
    int ls = l.size(), j1 = -1, j2 = -1, i, e;
    if (l.size() == 1)
        rep(i,0,n) if (i != l[0])
            if (!exc(l[0], i, l))
                return 0;
    do {
        j1 = random(n);
        do j2 = random(n); while (j1 == j2);
        e = exc(j1, j2, l);
    } while(e > ls);
    return e;
}

void solve() {
    vector<int> l;
    int step, cl, tr, i;
    for (tr = 0; tr < n * n; ++tr) {
        l.clear(); step = 0;

        srand(time(0) + tr * cl);
        init();
        for (cl = h(l); cl && step < n * n; cl = next(l), ++step);

        if (!cl) {
            rep(i,0,n) printf("%d\n", c[i] + 1);
            return;
        }
    }
}

int main() {
    while (scanf("%d", &n) != EOF) {
        n *= n;
        solve();
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值