codeforces round #230

来源:互联网 发布:屏幕取词翻译软件 编辑:程序博客网 时间:2024/05/01 16:27
codeforces_div230
A:
半径为n的圆,园内有一些整点,和它距离为1的点就连接起来,现在去掉一些点,使得圆内的点和圆外的点没有连接。
策略是选择圆内的点:
圆内选择肯定是靠近边界的点,如何选择?四个端点肯定是要选择的。(n, 0) (0, n) (0, -n), (-n, 0)四个点。
然后圆内的点,因为象限对称,只要考虑第一象限,如果横坐标为1,可以算出一个圆内的纵坐标y1,如果横坐标为2,也可以算出圆内的一个纵坐标y2。
那么肯定的是[[1,y1], [1, y2])的点都是要拿掉的。拿掉之后横坐标为1的点就没有和圆外相连接的了。那么用O(n)就可以推出有多少点,算前后纵坐标之差即可。

如果纵坐标相同,还是要把前一个点删除掉,因为前面一个点的上面肯定是一个圆外的点。

AC代码:

#include <cstdio>#include <cstring>#include <iostream>#include <cmath>using namespace std;long long n;long long ans;int main() {    cin >> n;    if (n == 0) {        printf("1\n");        return 0;    }    if (n == 1) {        printf("4\n");        return 0;    }    int pre = sqrt(n * n - 1 + 1e-10);    ans = 0;    for (long long i = 2; i <= n; i++) {        int now_y = (int)sqrt(n * n - i * i + 1e-10);        if (now_y == pre) {            ans += 1;        }        else {            ans = ans + (long long)(pre - now_y);        }        pre = now_y;    }    cout << ans * 4 + 4 << endl;    return 0;}




B:
经典汉诺塔问题,改成了费用问题。有几种移法
1:要原来一样,把n - 1移动到2,然后把最大的移动到3,现在变成了n - 1个盘子从2移动到3最小的费用。
2:把n - 1个盘子移动到3,然后把最大的移动到2,然后把n - 1个盘子移动到1,把最大的移动到3。
所以用dp[i][j][k][n],表示从i柱移动到j柱,辅助柱为k,移动n个盘子,状态转移为:

dp[i][j][k][n] = min(dp[i][k][j][n - 1] + t[i][j] + dp[k][j][i][n - 1], dp[i][j][k][n - 1] + t[i][k] + dp[j][i][k][n - 1] + t[k][j] + dp[i][j][k][n - 1]);

AC代码:

#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int MAX_NUMBER = 50;long long dp[4][4][4][MAX_NUMBER];int vis[4][4][4][MAX_NUMBER];long long money[4][4];int n;void dfs(int from, int to, int help, int number) {    if (vis[from][to][help][number] != -1) {        return ;    }    vis[from][to][help][number] = 1;    if (number == 1) {        vis[from][to][help][number] = 1;        long long temp_1 = money[from][to];        long long temp_2 = money[from][help] + money[help][to];        if (temp_1 < temp_2) {            dp[from][to][help][number] = temp_1;        }        else {            dp[from][to][help][number] = temp_2;        }        return ;    }    dfs(from, help, to, number - 1);    dfs(help, to, from, number - 1);    long long temp_1 = money[from][to] + dp[from][help][to][number - 1] + dp[help][to][from][number - 1];    dfs(from, to, help, number - 1);    dfs(to, from, help, number - 1);    long long temp_2 = money[from][help] + 2 * dp[from][to][help][number - 1] + dp[to][from][help][number - 1] + money[help][to];    if (temp_1 < temp_2) {        dp[from][to][help][number] = temp_1;    }    else {        dp[from][to][help][number] = temp_2;    }}int main() {    memset(vis, -1, sizeof(vis));    for (int i = 1; i <= 3; i++) {        for (int j = 1; j <= 3; j++) {            cin >> money[i][j];        }    }    cin >> n;    dfs(1, 3, 2, n);    long long ans = dp[1][3][2][n];    cout << ans << endl;}


0 0