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;
};