USACO Section 1.3

USACO Section 1.3

Mixing Milk
/*
    ID: beihai2013
    TASK:milk
    LANG: C++
*/
/*贪心选择消费最少的农人*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5000 + 5;
struct Node
{
    int u, v;
}node[MAXN];
bool cmp1(Node a, Node b){return a.u < b.u;}
int main()
{
    freopen("milk.in", "r",stdin);
    freopen("milk.out", "w", stdout);
    int n, m;
    while(scanf("%d%d", &n, &m) != EOF) {
        for(int i = 0 ; i < m ; i++) scanf("%d%d", &node[i].u, &node[i].v);
        int ans = 0;
        sort(node, node + m, cmp1);
        for(int i = 0 ; i < m ; i++) {
            if(n > node[i].v) ans += node[i].u * node[i].v, n -= node[i].v;
            else {
                ans += node[i].u * n;
                break;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

Barn Repair

/*
    ID: beihai2013
    TASK:barn1
    LANG: C++
*/
/*转换思维,寻找(m-1)个最大的连续0子串。同时注意首尾的0子串是不用放木板的*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200 + 5;
int g[MAXN], m, s, c, a[MAXN], cnt;
bool cmp(int a, int b){return a > b;}
int main()
{
    freopen("barn1.in", "r",stdin);
    freopen("barn1.out", "w", stdout);
    while(scanf("%d%d%d", &m, &s, &c) != EOF) {
        memset(g, 0, sizeof g);
        for(int i = 0 ; i < c ; i++) {
            int u;  scanf("%d", &u);
            g[u] = 1;
        }
        cnt = 0;
        int mark = 0;
        int f = 1;
        int head = 0;
        for(int i = 1 ; i <= s ; i++) {
            if(f && g[i] == 0) head++;
            else if(g[i] == 0) mark++;
            else {
                f = 0;
                a[cnt++] = mark;
                mark = 0;
            }
        }
        sort(a, a + cnt, cmp);
//        for(int i = 0 ; i < cnt ; i++) printf("%d ", a[i]);
//        printf("\n");
//        printf("head = %d, mark = %d\n", head, mark);
        int ans = 0;
        for(int i = 0 ; i < min(cnt, m - 1) ; i++) ans += a[i];
        printf("%d\n", s - ans - head - mark);
    }
    return 0;
}

Prime Crytarithm

/*
    ID: beihai2013
    TASK:crypt1
    LANG: C++
*/
/*枚举算式的每个数,大概复杂度1e5*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 10 + 2;
int use[MAXN], n;
int a[MAXN];
bool check(int u)
{
    while(u) {
        if(use[u % 10] == 0) return false;
        u /= 10;
    }
    return true;
}
int dfs(int cnt)
{
    if(cnt == 5) {
        int sum = a[0] * 100 + a[1] * 10 + a[2];
        int t1 = sum * a[4];
        int t2 = sum * a[3] * 10;
        if(t1 > 999 || t2 > 9990) return 0;
        else if(t1 + t2 > 9999) return 0;
        else if(check(t1) && check(t2 / 10) && check(t1 + t2)) return 1;
        else return 0;
    }
    int res = 0;
    for(int i = 0 ; i <= 9 ; i++) {
        if((cnt == 0 || cnt == 3) && i == 0) continue;
        if(use[i] == 1) {
            a[cnt] = i;
            res += dfs(cnt + 1);
        }
    }
    return res;
}
int main()
{
    freopen("crypt1.in", "r",stdin);
    freopen("crypt1.out", "w", stdout);
    while(scanf("%d", &n) != EOF) {
        memset(use, 0, sizeof use);
        for(int i = 0 ; i < n ; i++) {
            int u;  scanf("%d", &u);
            use[u] = 1;
        }
        printf("%d\n", dfs(0));
    }
    return 0;
}

Combination Lock

/*
    ID: beihai2013
    TASK:combo
    LANG: C++
*/
/*用全概率公式来做这个组合数学问题*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100 + 5;
int g[2][3], n, vis[2][MAXN];
int cnt[3];
int cal1(int u){while(u < 1) u += n; while(u > n) u -= n; return u;}
int cal2(int u){return u * u * u;}
int main()
{
    freopen("combo.in", "r",stdin);
    freopen("combo.out", "w", stdout);
    while(scanf("%d", &n) != EOF) {
        for(int i = 0 ; i < 2 ; i++) for(int j = 0 ; j < 3 ; j++) scanf("%d", &g[i][j]);
        int tsum = 1;
        for(int i = 0 ; i < 3 ; i++) {
            cnt[i] = 0;
            memset(vis, 0, sizeof vis);
            for(int j = -2 ; j <= 2 ; j++) {
                for(int k = 0 ; k < 2 ; k++) {
                    int temp = cal1(g[k][i] + j);
                    vis[k][temp] = 1;
                }
            }
            for(int j = 0 ; j < MAXN ; j++) if(vis[0][j] && vis[1][j]) cnt[i]++;
            tsum = tsum * cnt[i];
        }
        int res = 2 * cal2(min(5, n)) - tsum;
        printf("%d\n", res);
    }
    return 0;
}

WormHoles

/*
    ID: beihai2013
    TASK:wormhole
    LANG: C++
*/
/*
    看数据强行水过
    首先用dfs的方法枚举出分组方案dfs
    然后在此基础上,对每个点暴力走环check
    check里有两个参数,一个表示当前点,一个表示当前状态
    状态分两种,一种是走到当前点上面点的状态,一种是已经通过虫洞交换点的状态
    返回第一个走过两次的点(数据告诉我会出现一个点走过一次但是又走出边界的情况)
    如果没有返回-1
*/
/*
    标解用这样一种方法做
    首先判断枚举与当前点配对的点,然往下走
    当没有点未配对时,判环
    判环的方式在环中最多走n次,一次走同时完成走向最靠右边的一个点和通过虫洞转移到另一点的操作
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 12 + 3;
int x[MAXN], y[MAXN], n;
int p[MAXN][2];
int num[MAXN], vis[MAXN];
int match[MAXN], up[MAXN];
int check(int u, int cost)
{
    if(u == -1) return u;
    if(vis[u] == 2) return u;
    vis[u]++;
    if(cost == 0) return check(match[u], 1);
    else return check(up[u], 0);
}
int dfs(int cnt, int dep)
{
    if(dep == n) {
        int ok = 0;
        for(int i = 0 ; i <= n ; i++) vis[i] = 0;
        for(int i = 0 ; i < cnt ; i++) {
            for(int j = 0 ; j < 2 ; j++) {
                memset(vis, 0, sizeof vis);
                int u = p[i][j];
                int temp = -1;
                if(up[u] != -1) temp = check(up[u], 0);
                if(temp == -1) {
                    memset(vis, 0, sizeof vis);
                    vis[u] = 1;
                    temp = check(match[u], 1);
                }
                if(temp != -1) {
//                    printf("u = %d, temp = %d\n", u, temp);
                    ok = 1;
                    break;
                }
            }
        }
//        if(ok) {
//            for(int i = 0 ; i < cnt ; i++) {
//                for(int j = 0 ; j < num[i] ; j++) printf("%d ", p[i][j]);
//                printf("\n");
//            }
//            system("pause");
//        }
        return ok;
    }
    else {
        int res = 0;
        for(int i = 0 ; i < cnt ; i++) {
            if(num[i] < 2) {
                num[i]++;
                p[i][1] = dep;
                match[p[i][0]] = p[i][1];
                match[p[i][1]] = p[i][0];
                res += dfs(cnt, dep + 1);
                num[i]--;
            }
        }
        if(cnt < n / 2) {
            num[cnt]++, p[cnt][0] = dep;
            res += dfs(cnt + 1, dep + 1);
            num[cnt]--;
        }
        return res;
    }
}
int main()
{
    freopen("wormhole.in", "r", stdin);
    freopen("wormhole.out", "w", stdout);
    while(scanf("%d", &n) != EOF) {
        for(int i = 0 ; i < n ; i++) scanf("%d%d", x + i, y + i), swap(x[i], y[i]);
        memset(up, -1, sizeof up);
        for(int i = 0 ; i < n ; i++) {
            for(int j = 0 ; j < n ; j++) {
                if(i == j) continue;
                if(x[i] == x[j] && y[j] > y[i]) {
                    int ok = 1;
                    for(int k = 0 ; k < n ; k++) {
                        if(i == k || j == k) continue;
                        if(x[i] == x[k] && y[k] > y[i] && y[k] < y[j]) ok = 0;
                    }
                    if(ok) up[i] = j;
                }
            }
        }
        memset(num, 0, sizeof num);
        p[0][0] = 0, num[0] = 1;
        printf("%d\n", dfs(1, 1));
    }
    return 0;
}

Ski Course Design Lock
/*
ID: beihai2013
TASK: skidesign
LANG: C++
*/
/三分答案/
/标解用暴力所有可能答案的方法/

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000 + 5;
int h[MAXN], n;
int cal(int u)
{
    int res = 0;
    for(int i = 0 ; i < n ; i++) {
        if(h[i] < u) res += (u - h[i]) * (u - h[i]);
        else if(h[i] > u + 17) res += (h[i] - u - 17) * (h[i] - u - 17);
    }
    return res;
}
int main()
{
    freopen("skidesign.in", "r", stdin);
    freopen("skidesign.out", "w", stdout);
    while(scanf("%d", &n) != EOF) {
        for(int i = 0 ; i < n ; i++) scanf("%d", h + i);
        int le = 0, re = 100;
        while(le < re - 1) {
            int len = (re - le + 1) / 3;
            if(cal(le + len) >= cal(re - len)) le = le + len;
            else re = re - len;
        }
//        printf("le = %d, re = %d\n", le, re);
        int t1 = cal(le), t2 = cal(re);
        printf("%d\n", min(t1, t2));
    }
    return 0;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值