2014百度之星资格赛4题
因为都是中文题。题意就不写了。
A、Energy Conversion
这题先推断一下能量能否添加,然后再依据添加这个公式去求出一个等比公式。就能够直接求出须要添加几次了
B、Disk Schedule
首先轨道转移和读取数据时间肯定是要花进去的,剩下就是看转的那部分时间,从0,0開始,回到0。0。中间经过n个点,转化为经典的双调欧几里得DP。就能够求出答案了
C、Xor Sum
从高位建字典树,然后贪心。尽量选择0,1不同的位置去放
D、Labyrinth
非经常见的动态规划,dp[i][j][k]代表在(i, j)这个点,从k方向来的状态。然后随便搞搞记忆化搜索
代码:
A:
#include <stdio.h>
#include <string.h>
#include <math.h>
const double eps = 1e-9;
int t;
double n, m, v, k;
int main() {
scanf("%d", &t);
while (t--) {
scanf("%lf%lf%lf%lf", &n, &m, &v, &k);
long long ans;
if (m >= n) {printf("0\n"); continue;}
if ((m - v) * k > m) ans = (long long)(ceil(log((n + v * k / (1 - k)) / (m + v * k / (1 - k))) / log(k)) + eps);
else ans = -1;
printf("%lld\n", ans);
}
return 0;
}
B:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = 1005;
int t, n, dp[N][N];
struct CD {
int t, s;
void read() {
scanf("%d%d", &t, &s);
}
} cd[N];
int dis(int i, int j) {
int a = cd[i].s, b = cd[j].s;
return min((a - b + 360) % 360, (b - a + 360) % 360);
}
const int INF = 0x3f3f3f3f;
int main() {
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
cd[1].t = 0; cd[1].s = 0;
int ans = n * 10;
n++;
for (int i = 2; i <= n; i++)
cd[i].read();
ans += cd[n].t * 800;
int an = INF;
dp[2][1] = dis(2, 1);
for (int i = 3; i <= n; i++) {
dp[i][i - 1] = INF;
for (int j = 1; j < i - 1; j++) {
dp[i][j] = dp[i - 1][j] + dis(i, i - 1);
dp[i][i - 1] = min(dp[i][i - 1], dp[i - 1][j] + dis(j, i));
if (i == n) an = min(an, dp[i][j] + dis(j, i));
}
}
printf("%d\n", ans + min(an, dp[n][n - 1] + dis(n - 1, n)));
}
return 0;
}
C:
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
int t, n, m, ans[105], an, rtn;
__int64 num, mi[50];
struct Tree {
int value;
int left, right;
void init() {
value = 0;
left = -1;
right = -1;
}
Tree(){}
Tree(int v, int l, int r) {
value = v;
left = l;
right = r;
}
} root[5000005];
void insert(Tree &roo, __int64 num, int d) {
if (d == 0) return;
__int64 t = 0;
if (num >= mi[d - 1]) {
num -= mi[d - 1];
t = 1;
}
if (t == 0) {
if (roo.left == -1) {
roo.left = ++rtn;
root[roo.left] = Tree(0, -1, -1);
}
insert(root[roo.left], num, d - 1);
}
else {
if (roo.right == -1) {
roo.right = ++rtn;
root[roo.right] = Tree(1, -1, -1);
}
insert(root[roo.right], num, d - 1);
}
}
void find(Tree roo, __int64 num, int d) {
if (d == 0) return;
__int64 t = 0;
if (num >= mi[d - 1]) {
num -= mi[d - 1];
t = 1;
}
if (t == 0) {
if (roo.right == -1) {
find(root[roo.left], num, d - 1);
ans[d - 1] = 0;
}
else {
ans[d - 1] = 1;
find(root[roo.right], num, d - 1);
}
}
else {
if (roo.left == -1) {
ans[d - 1] = 1;
find(root[roo.right], num, d - 1);
}
else {
ans[d - 1] = 0;
find(root[roo.left], num, d - 1);
}
}
}
int main() {
mi[0] = 1;
for (int i = 1; i <= 50; i++)
mi[i] = mi[i - 1] * 2;
int cas = 0;
scanf("%d", &t);
while (t--) {
rtn = 0;
root[0] = Tree(0, -1, -1);
scanf("%d%d", &n, &m);
while (n--) {
scanf("%I64d", &num);
insert(root[0], num, 50);
}
printf("Case #%d:\n", ++cas);
while (m--) {
scanf("%I64d", &num);
find(root[0], num, 50);
__int64 out = 0;
for (int i = 50; i >= 0; i--)
out = out * 2 + ans[i];
printf("%I64d\n", out);
}
}
return 0;
}
D:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
int t, n, m, g[105][105], vis[105][105][3], dp[105][105][3];
const int d[3][2] = {1, 0, -1, 0, 0, 1};
int dfs(int x, int y, int v) {
int &ans = dp[x][y][v];
if (vis[x][y][v]) return ans;
vis[x][y][v] = 1;
ans = -INF;
if (x == 0 && y == m - 1) {
return ans = g[x][y];
}
for (int i = 0; i < 3; i++) {
if ((v == 0 && i == 1) || (v == 1 && i == 0)) continue;
int xx = x + d[i][0];
int yy = y + d[i][1];
if (xx < 0 || xx >= n || yy < 0 || yy >= m) continue;
ans = max(ans, dfs(xx, yy, i) + g[x][y]);
}
return ans;
}
int main() {
scanf("%d", &t);
int cas = 0;
while (t--) {
memset(vis, 0, sizeof(vis));
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
scanf("%d", &g[i][j]);
printf("Case #%d:\n", ++cas);
printf("%d\n", dfs(0, 0, 0));
}
return 0;
}