2021牛客多校2

F. Girlfriend

题目大意: 给出 A,B,C,D,的坐标,和 K1,K2 求满足
| AP1 | >= K1 | BP1 | 和 | CP2 | >= K2 | DP2 | 条件下的 P1 所在的空间P2 所在的空间相交体积

解题思路: 首先可以发现满足 | AP1 | >= K1 | BP1 | 的 P1 所在区域为空间中的球,下面给出推导;
在这里插入图片描述

这个方程在满足 t1 ^ 2 + t1 + t2 ^ 2 + t2 + t3 ^ 2 + t3大于 0 的时候才满足球的方程,题目数据应该会满足的吧
接下来题目要求的就是两个球冠的体积和
下面的图,左边标注阴影的是球冠,右边是两球相交的截面图
是不是非常清楚呢
在这里插入图片描述

球冠的计算公式为 Pi * h * h * (r * 3 - h) / 3;
下面给出一重积分计算得出公式的过程
在这里插入图片描述

在这里插入图片描述

然后就是代码
求解的时候注意特判 不相交包含 的关系

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<P, P> PP;
const int INF = 0x3f3f3f3f;
const int MAX_N = 1e6 + 10;
const int MOD = 1e9 + 7;
const double esp = 1e-9;
const double pi = 4.0 * atan(1.0);
int n;
double x[4], y[4], z[4], k[2];
double calc(double a1, double b1, double c1, double r1, double a2, double b2, double c2, double r2){
    double dis = sqrt((a1 - a2) * (a1 - a2) + (b1 - b2) * (b1 - b2) + (c1 - c2) * (c1 - c2));
    double res = 0;
    if(dis >= r1 + r2){
        res = 0;
    }else if(dis + r1 <= r2){
        res = (4.0 / 3.0) * pi * r1 * r1 * r1;
    }else if(dis + r2 <= r1){
        res = (4.0 / 3.0) * pi * r2 * r2 * r2;
    }else{
        double _cos = (r1 * r1 + dis * dis - r2 * r2) / (2.0 * r1 * dis);
        double h = r1 * (1 - _cos);
        res += pi / 3.0 * h * h * (3.0 * r1 - h);
        _cos = (r2 * r2 + dis * dis - r1 * r1) / (2.0 * r2 * dis);
        h = r2 * (1 - _cos);
        res += pi / 3.0 * h * h * (3.0 * r2 - h);
    }
    return res;
}
void solve(){
    double a1, b1, c1, r1, a2, b2, c2, r2;
    double t, kk, d;
    for(int i = 0; i < 4; i++){
        scanf("%lf%lf%lf", &x[i], &y[i], &z[i]);
    }
    scanf("%lf%lf", &k[0], &k[1]);
    t = (k[0] * k[0] - 1); kk = k[0] * k[0];
    a1 = (kk * x[1] - x[0]) / t; b1 = (kk * y[1] - y[0]) / t; c1 = (kk * z[1] - z[0]) / t;
    d = x[0] * x[0] + y[0] * y[0] + z[0] * z[0] - kk * (x[1] * x[1] + y[1] * y[1] + z[1] * z[1]);
    r1 = sqrt(d / t + a1 * a1 + b1 * b1 + c1 * c1);
    t = (k[1] * k[1] - 1); kk = k[1] * k[1];
    a2 = (kk * x[3] - x[2]) / t; b2 = (kk * y[3] - y[2]) / t; c2 = (kk * z[3] - z[2]) / t;
    d = x[2] * x[2] + y[2] * y[2] + z[2] * z[2] - kk * (x[3] * x[3] + y[3] * y[3] + z[3] * z[3]);
    r2 = sqrt(d / t + a2 * a2 + b2 * b2 + c2 * c2);
    printf("%.3f\n", calc(a1, b1, c1, r1, a2, b2, c2, r2));
}
int main(){
    int TCASE = 1;
    scanf("%d", &TCASE);
    while(TCASE--) solve();
    return 0;
}

I.Penguins

题目大意: 给出一个矩阵表示地图,’#’ 表示障碍物,左企鹅从左边的(20,20)出发,目的地是(1,20),右企鹅从右边的(20,1)出发,目的地是(1,1);求最小步数,并输出其中一种方案。
在这里插入图片描述
如果一次移动,某个企鹅到达障碍物或者越界的时候,那么它的移动被忽略。

样例:

input:
#................... .............##...#.
.................... .......#.....#.....#
.........#...#.#.... ...#....#...........
#........#.......... ...#..#.............
........#......#.... ..#.#......#.#.....#
......#.#..#.#....#. .......##.....##...#
....#...........#..# ....................
.##................. ...........#..#...#.
.....#.#........#.#. #.........#.#.......
.................... ..#....#..........#.
....#.#..........#.. .#.........#..#..#..
.........#.......#.. ..#.................
...#..#......#...#.. ......#.............
...........#...#.... ....................
..##..#.#....#..#... ..............#...#.
.#..#...#.#.....##.. .........#.#...#....
.#.........#........ ..............#.#...
..##.#........#...#. ##..................
....##.#............ .......#.....#......
..........##........ .#..#.#...........#.

output:
27
LULLUURRUUUUUUULUUUUURRUUUU
#..................A A............##...#.
...................A A......#.....#.....#
.........#...#.#...A A..#....#...........
#........#.........A A..#..#.............
........#......#.AAA AA#.#......#.#.....#
......#.#..#.#...A#. .A.....##.....##...#
....#...........#A.# .A..................
.##..............A.. .A.........#..#...#.
.....#.#........#A#. #A........#.#.......
.................AA. AA#....#..........#.
....#.#..........#A. A#.........#..#..#..
.........#.......#A. A.#.................
...#..#......#...#A. A.....#.............
...........#...#..A. A...................
..##..#.#....#..#.A. A.............#...#.
.#..#...#.#.....##A. A........#.#...#....
.#.........#....AAA. AAA...........#.#...
..##.#........#.A.#. ##A.................
....##.#........AAA. AAA....#.....#......
..........##......AA A#..#.#...........#.

解题思路: 跑一遍 BFS

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<P, P> PP;
const int INF = 0x3f3f3f3f;
const int MAX_N = 1e6 + 10;
const int MOD = 1e9 + 7;
const double esp = 1e-9;
int n, k;
char sl[30][30], sr[30][30];
char res[1000];
int dx[4] = {1, 0, 0, -1};
int dy[4] = {0, -1, 1, 0};
int d[30][30][30][30];
PP pre[30][30][30][30];
void solve(){
    for(int i = 0; i < 20; i++){
        for(int j = 0; j < 20; j++){
            for(int k = 0; k < 20; k++){
                for(int l = 0; l < 20; l++){
                    d[i][j][k][l] = INF;
                }
            }
        }
    }
    for(int i = 0; i < 20; i++){
        scanf("%s", sl[i]);
        scanf("%s", sr[i]);
    }
    d[19][19][19][0] = 0;
    queue<PP> que;
    que.push(PP(P(19, 19), P(19, 0)));
    int xl, yl, xr, yr;
    int txl, tyl, txr, tyr;
    while(que.size()){
        PP pp = que.front(); que.pop();
        P pl = pp.first, pr = pp.second;
        xl = pl.first, yl = pl.second, xr = pr.first, yr = pr.second;
        for(int i = 0; i < 4; i++){
            txl = xl + dx[i]; tyl = yl + dy[i];
            txr = xr + dx[i]; tyr = yr - dy[i];
            //左右企鹅都不会越界
            if((txl >= 0 && txl <= 19 && tyl >= 0 && tyl <= 19) && (txr >= 0 && txr <= 19 && tyr >= 0 && tyr <= 19)){
            	//左右企鹅都走到障碍物,则没必要执行这次操作
                if(sl[txl][tyl] == '#' && sr[txr][tyr] == '#') continue;
                //左企鹅走到障碍物
                if(sl[txl][tyl] == '#') txl = xl, tyl = yl;
                //右企鹅走到障碍物
                if(sr[txr][tyr] == '#') txr = xr, tyr = yr;
                if(d[txl][tyl][txr][tyr] > d[xl][yl][xr][yr] + 1){
                    d[txl][tyl][txr][tyr] = d[xl][yl][xr][yr] + 1; que.push(PP(P(txl, tyl), P(txr, tyr)));
                    pre[txl][tyl][txr][tyr] = PP(P(xl, yl), P(xr, yr));
                }
            //右企鹅越界
            }else if(txl >= 0 && txl <= 19 && tyl >= 0 && tyl <= 19 && sl[txl][tyl] != '#'){
                txr = xr, tyr = yr;
                if(d[txl][tyl][txr][tyr] > d[xl][yl][xr][yr] + 1){
                    d[txl][tyl][txr][tyr] = d[xl][yl][xr][yr] + 1; que.push(PP(P(txl, tyl), P(txr, tyr)));
                    pre[txl][tyl][txr][tyr] = PP(P(xl, yl), P(xr, yr));
                }
            //左企鹅越界
            }else if(txr >= 0 && txr <= 19 && tyr >= 0 && tyr <= 19 && sr[txr][tyr] != '#'){
                txl = xl, tyl = yl;
                if(d[txl][tyl][txr][tyr] > d[xl][yl][xr][yr] + 1){
                    d[txl][tyl][txr][tyr] = d[xl][yl][xr][yr] + 1; que.push(PP(P(txl, tyl), P(txr, tyr)));
                    pre[txl][tyl][txr][tyr] = PP(P(xl, yl), P(xr, yr));
                }
            }
        }
    }
    int t = 0;
    xl = 0, yl = 19, xr = 0, yr = 0;
    sl[0][19] = 'A'; sr[0][0] = 'A';
    while(xl != 19 || yl != 19 || xr != 19 || yr != 0){
        PP pp = pre[xl][yl][xr][yr];
        P pl = pp.first, pr = pp.second;
        txl = pl.first, tyl = pl.second, txr = pr.first, tyr = pr.second;
        if(txl > xl || txr > xr) res[t++] = 'U';
        else if(txl < xl || txr < xr) res[t++] = 'D';
        else if(tyl < yl || tyr > yr) res[t++] = 'R';
        else if(tyl > yl || tyr < yr) res[t++] = 'L';
        xl = txl; yl = tyl; xr = txr; yr = tyr;
        sl[txl][tyl] = 'A'; sr[txr][tyr] = 'A';
//        cout << xl << ' ' << yl << ' ' << xr << ' ' << yr << '\n';
    }
    printf("%d\n", t);
    for(int i = t - 1; i >= 0; i--) printf("%c", res[i]);
    printf("\n");
    for(int i = 0; i < 20; i++){
        printf("%s ", sl[i]);
        printf("%s\n", sr[i]);
    }
}
int main(){
    int TCASE = 1;
//    scanf("%d", &TCASE);
    while(TCASE--) solve();
    return 0;
}

K.Stack

题目大意: 有一个数组 a,下标从 1 到 n,从 a[1] 遍历到 a[n],同时有一个栈,如果栈为空或者,a[i] 大于栈顶元素,则直接入栈,否则一直弹出栈顶元素,另一个数组 b 记录此时栈的元素个数。给出 n 和 k 个 b[i] 的值,求一种 a 的排列,不存在则输出 -1。
数据保证 a 的元素为一个排列,即 a[i] >= 1 && a[i] <= n; 任意 i, j, 如果 i,j不同,则 a[i] 和 a[j] 不同。

样例1:
输入
5 2
2 2
5 4
输出:
1 2 5 3 4
样例2:
输入
10 1
1 10
输出
-1
解题思路: 首先假设已知 b 数组的每个元素,且存在解,我们可以发现,b[i+1] 如果大于 b[i],则 b[i+1] = b[i] + 1; b[i+1] 如果小于等于 b[i],则 b[i+1] >= 1 && b[i+1] <= b[i];
通过已知 b[i] 的值,可以知道此时栈中需要有 b[i] - 1 个值小于 a[i],如果从后往前遍历,用一个栈来表示题目中的栈,当元素个数小于 b[i] ,则一直从小到大加入元素,否则栈顶作为 a[i],同时弹出栈顶元素,这样得出的数组总能满足条件。感觉是题目中栈的逆过程。严格证明我并不清楚
然后可以得知,如果然 b[i] 未知的由前一个一直的加 1 得来,最后存在差大于 1 得 b[i] 与 b[i+1] 得话,则无解,否则总有解。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<double, double> P;
const int INF = 0x3f3f3f3f;
const int MAX_N = 1e6 + 10;
const int MOD = 1e9 + 7;
const double esp = 1e-9;
int n, k;
int b[MAX_N], res[MAX_N];
void solve(){
    int p, x;
    scanf("%d%d", &n, &k);
    for(int i = 0; i < k; i++){
        scanf("%d%d", &p, &x);
        b[p] = x;
    }
    for(int i = 1; i <= n; i++){
        if(b[i] == 0) b[i] = b[i - 1] + 1;
        //无解结束
        if(b[i] > b[i - 1] + 1){
            printf("-1\n"); return;
        }
    }
    stack<int> s;
    int t = 1;
    for(int i = n; i >= 1; i--){
    	//栈中元素少了
        while(s.size() < b[i]) s.push(t++);
        res[i] = s.top();
        s.pop();
    }
    for(int i = 1; i < n; i++)
        printf("%d ", res[i]);
    printf("%d\n", res[n]);
}
int main(){
    int TCASE = 1;
//    scanf("%d", &TCASE);
    while(TCASE--) solve();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值