|
思路: 这题的背景是亮点,描述如下: Background Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes that they feature two different genders and that they only interact with bugs of the opposite gender. In his experiment, individual bugs and their interactions were easy to identify, because numbers were printed on their backs. Problem Given a list of bug interactions, decide whether the experiment supports his assumption of two genders with no homosexual bugs or if it contains some bug interactions that falsify it.
Hopper 在研究某种稀有虫子的性行为。他假设虫子们有两种不同的性别,而且它们只跟异性发生关系。 在他的试验里,每个虫子和它的性行为都很容易辨认,因为它们的背后印着号码。 给出一些虫子的性行为,确定是否有同性恋的虫子能推翻这个假设。
同性恋确实让人无法接受,无论是人还是虫子。。
这题的解法不是亮点,就是普通的并查集,数据量非常庞大,需要路径压缩。
#include <stdio.h> #include <string.h>
int N, T, set[2048], val[2048];
inline int find(int idx) { static int stk[2048], i;
for (i = 0; set[idx]; i++) { stk[i] = idx; idx = set[idx]; } for (i--; i >= 0; i--) { val[stk[i]] ^= val[set[stk[i]]]; set[stk[i]] = idx; }
return idx; }
int main() { int i, j, a, b, t, m, r;
scanf("%d", &T); for (t = 1; t <= T; t++) { scanf("%d%d", &N, &m); memset(set, 0, (N + 1) * 4); memset(val, 0, (N + 1) * 4); r = 0; while (m--) { scanf("%d%d", &a, &b); i = find(a); j = find(b); if (i == j) r |= val[a] == val[b]; else { set[i] = b; val[i] = !val[a]; } } printf("Scenario #%d:\n%s\n\n", t, r ? "Suspicious bugs found!" : "No suspicious bugs found!" ); }
return 0; }
摘要: 思路:继推箱子以后,又发现POJ上有这类题目,哈哈。这次是给出一条贪食蛇当前的状态、墙的位置、食物的位置。求吃到食物需要走的最小的步数。这类题目是相当牛逼的!高手的速度可以做到很BT的。在 status 上面就看到有 0ms 的!相当震惊,如此庞大的数据量能做到 0ms,肯定是神牛!后来搜了一下,还找到了那位神牛的博客,看了一下,发现看不大懂,杯具。。哪一天有空,一定会再想一下这道题的。一开始想了... 阅读全文
思路: 四个字:能放就放。。
#include <stdio.h> #include <stdlib.h>
int arr[10032][2], N, L, ans;
int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; }
inline int max(int a, int b) { return a > b ? a : b; }
int main() { int i, p, c;
freopen("e:\\test\\in.txt", "r", stdin);
scanf("%d%d", &N, &L); for (i = 0; i < N; i++) scanf("%d%d", &arr[i][0], &arr[i][1]); qsort(arr, N, sizeof(arr[0]), cmp);
for (i = p = 0; p < N; ) { i = max(i, arr[p][0]); c = (arr[p][1] - i + L - 1) / L; i += c * L; ans += c; while (p < N && i >= arr[p][1]) p++; }
printf("%d\n", ans);
return 0; }
摘要: 思路:这题没有啥好的方法了,看来。用组合C(K, D)枚举所有可能的疾病集合。其实复杂度很高的,C(15, 7) 都不知道多大了。但是数据比较弱。用别人的代码试了一下,用STL里面的全排列生成函数,都可以 60ms AC。下面的代码,没有用STL里面的函数,我以为会快一点,结果慢了不少,200+ms。。原理就是把16位分成2个8位来处理。#include <stdio.h>... 阅读全文
摘要: 思路:每个石头可以分为两个波,一个高峰波,一个低谷波。每个波可以分为很多个水平方向的波。每个水平方向的波有三种情况,起始点的位置:1. 位于 B1 左边2. 位于 B1,B2 中间3. 位于 B2 右边其中第2种情况有点麻烦,多次往返的话要一次算完。代码:#include <stdio.h>#include <string.h>int P,&... 阅读全文
思路: 有油的时候能走多远就走多远,看能否走到目的地。 如果走不到,就必须要加一次油,途中会遇到很多加油站,一定要选油最多的那个。 这很容易理解,因为如果你只加这一次,越多当然越好。如果要以后还要加,那能走远一点选择也多一点。 重复这样的过程就可以求解了。可以用堆维护加油站中的油量。 杯具:稍稍修改了一下堆的写法,结果WA两次。。 代码:
#include <stdio.h> #include <stdlib.h>
#define MAX_N 10032
struct node { int x, f; };
struct node stop[MAX_N]; int N, L, P; int heap[MAX_N], heap_size;
inline void shift_up(int idx) { int val = heap[idx]; while (idx > 1 && heap[idx/2] < val) { heap[idx] = heap[idx/2]; idx /= 2; } heap[idx] = val; }
inline void shift_down(int idx) { int val = heap[idx]; while (1) { idx *= 2; if (idx > heap_size) break; if (idx + 1 <= heap_size && heap[idx + 1] > heap[idx]) idx++; if (val >= heap[idx]) break; heap[idx/2] = heap[idx]; } heap[idx/2] = val; }
int cmp(const void *a, const void *b) { return ((struct node *)b)->x - ((struct node *)a)->x; }
inline void push(int val) { heap[++heap_size] = val; shift_up(heap_size); }
inline void pop() { heap[1] = heap[heap_size--]; shift_down(1); }
int main() { int i, x, t;
freopen("e:\\test\\in.txt", "r", stdin);
scanf("%d", &N); for (i = 0; i < N; i++) scanf("%d%d", &stop[i].x, &stop[i].f); scanf("%d%d", &L, &P); qsort(stop, N, sizeof(stop[0]), cmp);
push(P); x = L; i = 0; for (t = 0; heap_size && x > 0; t++) { x -= heap[1]; pop(); while (i < N && x <= stop[i].x) push(stop[i++].f); } printf("%d\n", x <= 0 ? t - 1 : -1);
return 0; }
思路: 每次放钱的时候,遵循两个原则来寻找最优方案: 1. 不能用面额小的组成面额大的 2. 所有方案中取最接近 C 的那个 就这样一次次的放,放到没钱为止。 注意,由于货币的数量较大,如果最优方案可以执行多次,那就一次过执行完。
#include <stdio.h> #include <stdlib.h>
#define MAX_N 64
struct node { int val, cnt; }; struct node coin[MAX_N]; int N, C, best, best_idx, ans, need[MAX_N];
inline int min(int a, int b) { return a < b ? a : b; }
int cmp(const void *a, const void *b) { return ((struct node *)a)->val - ((struct node *)b)->val; }
inline int put(int idx, int val) { int n;
n = min(coin[idx].cnt, (C - val - 1) / coin[idx].val); val += coin[idx].val * n; if (coin[idx].cnt > n) { if (!best || val + coin[idx].val < best) { best = val + coin[idx].val; best_idx = idx; } } need[idx] = n;
return val; }
inline int can() { int i, val;
best = val = 0; for (i = N - 1; i >= 0; i--) val = put(i, val);
return best; }
inline void update() { int i, cnt;
cnt = 100000000; need[best_idx]++; for (i = N - 1; i >= best_idx; i--) if (need[i]) cnt = min(cnt, coin[i].cnt / need[i]); for (i = N - 1; i >= best_idx; i--) coin[i].cnt -= cnt * need[i]; ans += cnt; }
int main() { int i;
scanf("%d%d", &N, &C); for (i = 0; i < N; i++) scanf("%d%d", &coin[i].val, &coin[i].cnt); qsort(coin, N, sizeof(coin[0]), cmp); while (coin[N - 1].val >= C) { ans += coin[N - 1].cnt; N--; } while (can()) update(); printf("%d\n", ans);
return 0; }
摘要: 属于状态型的动态规划,特难搞的那一类,状态一多,转换的时候难免遗漏一两个。这题还算,借助数据搞出来了,漏了两个转移,结果一组数据过不了。后来加上就AC了,时间还行,32MS。思路:从左往右开始放矩形,假设现在准备摆放第i列之后的矩形。实际上我们只关注第i-1列是怎么摆的,前面怎么摆都无所谓。所以,第i列牛的状态 + 第i-1列摆放的状态 -> 第i列摆放的状态摆放的状态有五种:1. 光上面有... 阅读全文
看到这道题,忽然想到,这就是大一时候C++考试的最后一题啊! 叫写一个程序,计算今天是星期几。 那时候记得写满了半张卷子。。八成还没写对。 不过今天,只用了5行! 我感到很由衷的高兴,面包会有的,牛奶会有的,脑残只是暂时的!
#include <stdio.h>
int days[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
char *weeks[] = { "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday" };
int main() { int y, m, d, w;
freopen("e:\\test\\in.txt", "r", stdin);
scanf("%d%d%d", &y, &m, &d); d += (y - 1799)*365 - 1; if (m <= 2) y--; d += (y/4 - 449) - (y/100 - 17) + y/400 - 4 + days[m - 1]; w = (d + 1) % 7; printf("%s\n", weeks[w]);
return 0; }
这题看起来很屌。 但是实际上走到每个点之后,速度必然是当前点和左上角点的差值的倒数。 所以,每个点到其他点的所花费的时间都是这个点自己的值决定的。 而且没可能经过一个点两次的,因为经过两次肯定是浪费时间的。 问题就变成了求最短路径。
注意: 这题的精度很莫名其妙,用C++可以AC的,G++、GCC都是WA。 不能用整数来保存时间,虽然看上去位数是够用的,但是遇到比较屌的数据就挂了。 就在这个问题上杯具了很久。
#include <stdio.h> #include <math.h>
#ifndef _countof #define _countof(x) (sizeof(x)/sizeof(x[0])) #endif
#define SIZE 128
int map[SIZE][SIZE], R, C, V; double D[SIZE][SIZE], _tbl[128], *tbl = &_tbl[64]; int queue[65536][2], head, tail; int vis[SIZE][SIZE];
inline void push(int y, int x, double d) { if (y < 0 || y >= R || x < 0 || x >= C) return ; if (d > D[y][x]) return ; D[y][x] = d; if (vis[y][x]) return ; vis[y][x] = 1; queue[tail][0] = y; queue[tail][1] = x; tail++; tail &= _countof(queue) - 1; }
inline void pop(int *y, int *x) { *y = queue[head][0]; *x = queue[head][1]; head++; head &= _countof(queue) - 1; vis[*y][*x] = 0; }
int main() { int i, j; double d;
freopen("e:\\test\\in.txt", "r", stdin);
for (i = -64; i <= 64; i++) tbl[i] = pow(2.0, i);
scanf("%d%d%d", &V, &R, &C); for (i = 0; i < R; i++) { for (j = 0; j < C; j++) { scanf("%d", &map[i][j]); if (i || j) map[i][j] -= map[0][0]; D[i][j] = 1e80; } } map[0][0] = 0;
push(0, 0, 0); while (head != tail) { pop(&i, &j); d = D[i][j] + tbl[map[i][j]]; push(i + 1, j, d); push(i - 1, j, d); push(i, j + 1, d); push(i, j - 1, d); }
printf("%.2lf\n", D[R - 1][C - 1] / V); return 0; }
|