USACO Section 2.1

Section 2.1
The Castle:

/*
    ID: beihai2013
    TASK: castle
    LANG: C++
*/
/*
简单搜索凑出所有连通快,四进制表示四个方向也是写的很熟练的那种了
值得注意的是farthest是最靠近的意思
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 50 + 5;
int g[MAXN][MAXN];
int sccno[MAXN][MAXN], scccnt, num[MAXN];
int n, m;
int dx[] = {0, -1, 0, 1};
int dy[] = {-1, 0, 1, 0};
bool validPos(int x, int y){if(x >= 0 && x < n && y >= 0 && y < m) return true; else return false;}
void dfs(int x, int y)
{
    sccno[x][y] = scccnt;
    num[scccnt]++;
    for(int i = 0 ; i < 4 ; i++) {
        if((1 << i) & g[x][y]) continue;
        int tx = dx[i] + x, ty = dy[i] + y;
        if(!validPos(tx, ty)) continue;
        if(sccno[tx][ty] == 0) dfs(tx, ty);
    }
}
int main()
{
    freopen("castle.in", "r", stdin);
    freopen("castle.out", "w", stdout);
    while(scanf("%d%d",&m, &n) != EOF) {
        for(int i = 0 ; i < n ; i++) for(int j = 0 ; j < m ; j++) scanf("%d", &g[i][j]);
        memset(sccno, 0, sizeof sccno);
        scccnt = 0;
        for(int i = 0 ; i < n ; i++) {
            for(int j = 0 ; j < m ; j++) {
                if(sccno[i][j] == 0) {
                    num[++scccnt] = 0;
                    dfs(i, j);
                }
            }
        }
//        for(int i = 0 ; i < n ; i++) {
//            for(int j = 0 ; j < m ; j++) printf("%d ", sccno[i][j]);
//            printf("\n");
//        }
//        system("pause");
        printf("%d\n", scccnt);
        int res1 = 0, res2 = 0;
        int resx, resy, dir;
        for(int y = 0 ; y < m ; y++) {
            for(int x = n - 1 ; x >= 0 ; x--) {
                res1 = max(res1, num[sccno[x][y]]);
                for(int k = 1 ; k < 3 ; k++) {
                    int tx = x + dx[k];
                    int ty = y + dy[k];
                    if(validPos(tx, ty) && sccno[x][y] != sccno[tx][ty]) {
                        if(res2 < num[sccno[x][y]] + num[sccno[tx][ty]]) {
                            res2 = num[sccno[x][y]] + num[sccno[tx][ty]];
                            resx = x, resy = y;
                            dir = k;
                        }
                    }
                }
            }
        }
        printf("%d\n%d\n", res1, res2);
        printf("%d %d %s\n", resx + 1, resy + 1, dir == 1 ? "N" : "E");
    }
    return 0;
}
/*
5 5
3 2 6 3 6
1 8 4 1 4
13 7 13 9 4
3 0 2 6 5
9 8 8 12 13
*/

Ordered Fraction:

/*
    ID: beihai2013
    TASK: frac1
    LANG: C++
*/
/*
    每个分母存一个已经用了多少个分子的数组
    如果分子和分母不是最简分数的话则跳过
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 160 + 5;
int num[MAXN];
int gcd(int a, int b){return b == 0 ? a : gcd(b, a % b);}
int main()
{
    freopen("frac1.in", "r", stdin);
    freopen("frac1.out", "w", stdout);
    int n;
    while(scanf("%d", &n) != EOF) {
        for(int i = 1 ; i <= n ; i++) num[i] = 1;
        printf("0/1\n");
        int cnt = n * (n + 1) / 2 - n;
        while(cnt > 0) {
            int son, mother;
            double res = 1;
            for(int i = 1 ; i <= n ; i++) {
                if(num[i] >= i) continue;
                while(num[i] < i && gcd(num[i], i) != 1) {
                    num[i]++;
                    cnt--;
                }
                if(res > 1.0 * num[i] / (1.0 * i)) {
                    res = 1.0 * num[i] / (1.0 * i);
                    son = num[i], mother = i;
                }
            }
            num[mother]++;
            cnt--;
            printf("%d/%d\n", son, mother);
        }
        printf("1/1\n");
    }
    return 0;
}

Sorting a Three-Value Sequence:

/*
    ID: beihai2013
    TASK: sort3
    LANG: C++
*/
/*
    首先确定排序后的序列是一定的,111 222 3333
    然后分别知道1、2、3所在位置的合法区间[1,num[1]], [num[1]+1,num[1]+num[2]], [num[1]+num[2]+1,n],方便称为A、B、C
    那么,在A区间里的2有限转移到B里,剩余转移到C;其余同理
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000 + 5;
int g[MAXN], cnt[4][4], n, num[4];
int calPos(int u){if(u <= num[1]) return 1; else if(u <= num[1] + num[2]) return 2; else return 3;}
int main()
{
    freopen("sort3.in", "r", stdin);
    freopen("sort3.out", "w", stdout);
    while(scanf("%d", &n) != EOF) {
        memset(num, 0, sizeof num);
        memset(cnt, 0, sizeof cnt);
        for(int i = 1 ; i <= n ; i++) {
            scanf("%d", g + i);
            num[g[i]]++;
        }
        for(int i = 1 ; i <= n ; i++) {
            int mark = calPos(i);
            cnt[mark][g[i]]++;
        }

        int res = 0;
        if(cnt[1][2]) {
            res += cnt[1][2];
            int temp = min(cnt[1][2], cnt[2][1]);
            cnt[1][2] -= temp;
            cnt[2][1] -= temp;
            cnt[3][2] += cnt[1][2];
        }
        if(cnt[1][3]) {
            res += cnt[1][3];
            int temp = min(cnt[1][3], cnt[3][1]);
            cnt[1][3] -= temp;
            cnt[3][1] -= temp;
            cnt[2][3] += cnt[1][3];
        }
        if(cnt[2][3]) {
            res += cnt[2][3];
//            int temp = min(cnt[1][2], cnt[2][1]);
//            cnt[1][2] -= temp;
//            cnt[2][1] -= temp;
//            cnt[3][2] += cnt[1][2];
        }
        printf("%d\n", res);
    }
    return 0;
}

Healthy Holsteins:

/*
    ID: beihai2013
    TASK: holstein
    LANG: C++
*/
/*状压枚举*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 25 + 3;
int v[MAXN], w[MAXN][MAXN], n, m;
int tv[MAXN], out[MAXN], tout[MAXN];
int main()
{
    freopen("holstein.in", "r", stdin);
    freopen("holstein.out", "w", stdout);
    while(scanf("%d", &n) != EOF) {
        for(int i = 0 ; i < n ; i++) scanf("%d", v + i);
        scanf("%d", &m);
        for(int i = 0 ; i < m ; i++) for(int j = 0 ; j < n ; j++) scanf("%d", &w[i][j]);
        int res = m + 1;
        for(int i = 0 ; i < (1 << m) ; i++) {
            for(int j = 0 ; j < n ; j++) tv[j] = 0;
            for(int j = 0 ; j < m ; j++) {
                if((1 << j) & i)
                for(int k = 0 ; k < n ; k++) tv[k] += w[j][k];
            }
            int ok = 1;
            for(int j = 0 ; j < n ; j++) if(tv[j] < v[j]) ok = 0;
            if(ok == 1) {
                int cnt = 0;
                for(int j = 0 ; j < m ; j++) if((1 << j) & i) tout[cnt++] = j + 1;
                if(res > cnt) {
                    res = cnt;
                    for(int j = 0 ; j < cnt ; j++) out[j] = tout[j];
                }
                else if(res == cnt) {
                    int tok = 0;
                    for(int j = 0 ; j < res ; j++) {
                        if(out[j] < tout[j]) break;
                        else if(out[j] > tout[j]) {
                            tok = 1;
                            break;
                        }
                    }
                    if(tok) for(int j = 0 ; j < res ; j++) out[j] = tout[j];
                }
//                if(cnt == 2 && tout[0] == 2 && tout[1] == 4) printf("i = %d\n", i);
            }
        }
        printf("%d", res);
        for(int i = 0 ; i < res ; i++) printf(" %d", out[i]);
        puts("");

    }
    return 0;
}

Hamming Codes:

/*
    ID: beihai2013
    TASK: hamming
    LANG: C++
*/
/*
    我太蠢了……
    这题就是贪心暴力,每次找最小的值满足条件,下一次找值找比这个值大的最小值,还想了各种奇怪的记忆化搜索……
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 64 + 5;
const int MAXM = 8 + 2;
int out[MAXN];
int n, b, d;
void dfs(int u, int cnt)
{
    if(cnt == n) return;
    out[cnt] = u;
    for(int i = u + 1 ; i < (1 << b) ; i++) {
        int ok = 0;
        if(i == 127) ok = 1;
        int num = b;
        for(int j = 0 ; j <= cnt ; j++) {
            int temp = out[j] ^ i;
            int tnum = 0;
            for(int k = 0 ; k < b ; k++) if((1 << k) & temp) tnum++;
//            if(ok) printf("j = %d, out[j] = %d, temp = %d, tnum = %d\n", j, out[j], temp, tnum);
            num = min(num, tnum);
        }
        if(num >= d) {
            dfs(i, cnt + 1);
            break;
        }
    }
}
int main()
{
    freopen("hamming.in", "r", stdin);
    freopen("hamming.out", "w", stdout);
    while(scanf("%d%d%d", &n, &b, &d) != EOF) {
        dfs(0, 0);
        for(int i = 0 ; i < n ; i++) {
            if(i % 10) printf(" ");
            else if(i != 0) printf("\n");
            printf("%d", out[i]);
        }
        printf("\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值