第四次

本文提供了几道典型的算法竞赛题目解答过程,包括狗追小偷的逃逸问题、满二叉树成员关系判断及字符串匹配问题,展示了使用C/C++进行问题解决的方法和技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://acm.csu.edu.cn/OnlineJudge/problem.php?cid=2101&pid=6

题意:
狗追小偷,如果找到了他的足迹,则速度变为原来2倍,有若干个出口,问最后小偷能否顺利逃脱。
思路:
枚举每一个出口,从小偷开始bfs,如果下一个点满足条件(小偷到这个点的距离+到出口距离<狗到这个点距离+到出口距离+1 /2) 则可以转移,如果能转移到出口则可以逃脱~

#include <stdio.h>

int grid_width, grid_height;
char grid_sym[2510];
int grid_dist_kennel[2500];
int grid_dist_thief[2500];
int grid_dist_exit[2500];
int exits[200];

#define FFQC 2510
int ffq_pop_idx = 0, ffq_push_idx = 0;
int ffqp[FFQC], ffqd[FFQC];
void ffq_push(int pos, int depth) {
    ffqp[ffq_push_idx] = pos;
    ffqd[ffq_push_idx] = depth;
    ffq_push_idx = (ffq_push_idx + 1) % FFQC;
}
int ffq_pop(int *pos, int *depth) {
    if (ffq_pop_idx == ffq_push_idx) return 0;
    *pos = ffqp[ffq_pop_idx];
    *depth = ffqd[ffq_pop_idx];
    ffq_pop_idx = (ffq_pop_idx + 1) % FFQC;
    return 1;
}

void flood_fill(int start_pos, int *distances, int(*should_visit)(int, int)) {
    for (int i = 0; i < 2500; ++i) {
        distances[i] = -1;
    }

    ffq_push(start_pos, 0);
    int pos, depth;
    while (ffq_pop(&pos, &depth)) {
        if (distances[pos] == -1 && grid_sym[pos] != 'X' && should_visit(pos, depth)) {
            distances[pos] = depth;
            const int row = pos / grid_width;
            const int col = pos % grid_width;
            if (row > 0)               ffq_push(pos - grid_width, depth + 1);
            if (col > 0)               ffq_push(pos - 1,          depth + 1);
            if (col + 1 < grid_width)  ffq_push(pos + 1,          depth + 1);
            if (row + 1 < grid_height) ffq_push(pos + grid_width, depth + 1);
        }
    }
}

int should_visit_thief(int pos, int depth) {
    const int thief_exit_time = depth + grid_dist_exit[pos];
    const int dog_exit_time = grid_dist_kennel[pos] + (grid_dist_exit[pos] + 1) / 2;
    return thief_exit_time < dog_exit_time;
}
int should_visit_other(int pos, int depth) {
    return 1;
}

void handle_case() {
    int thief, kennel, num_exits = 0;
    for (int i = grid_width * grid_height; i > 0; --i) {
        switch (grid_sym[i]) {
            case 'T': thief = i; break;
            case 'K': kennel = i; break;
            case 'E': exits[num_exits++] = i;
        }
    }

    flood_fill(kennel, grid_dist_kennel, should_visit_other);
    for (int i = 0; i < num_exits; ++i) {
        flood_fill(exits[i], grid_dist_exit, should_visit_other);
        flood_fill(thief, grid_dist_thief, should_visit_thief);
        if (grid_dist_thief[exits[i]] >= 0) {
            puts("KEEP IT");
            return;
        }
    }
    puts("DROP IT");
}

int main() {
    while (scanf("%d %d ", &grid_width, &grid_height) == 2 && grid_width >= 3 && grid_height >= 3) {
        for (int row = 0; row < grid_height; ++row) {
            fgets(&grid_sym[row * grid_width], 60, stdin);
        }

        handle_case();
    }
}

http://acm.csu.edu.cn/OnlineJudge/problem.php?cid=2101&pid=0
题意: 一棵满二叉树代表一个家谱,定义几种成员关系,任意给定2个序号和b的性别,问a和b的关系。
找到最近公共祖先,根据a 到最近公共祖先的距离和a与b的距离之差即可判断出到底是什么关系,最近公共祖先只要找规律去求即可~

#include <stdio.h>

char *nth[] = {"1st", "2nd", "3rd"};
char *removed[] = {"once", "twice", "thrice"};
#define MF(m, f) sex == 'M' ? m : f

void handle_case(int id_a, int id_b, char sex) {
    int dist_a = 0, dist_b = 0;
    while (id_a != id_b) {
        if (id_a > id_b) dist_a++, id_a = (id_a - 1) / 2;
        else             dist_b++, id_b = (id_b - 1) / 2;
    }
    int smaller = dist_a < dist_b ? dist_a : dist_b;
    int delta = dist_a - smaller + dist_b - smaller;

    if (dist_a == 0 && dist_b == 0) {
        puts("self");
    } else if (dist_a == 1 && dist_b == 1) {
        puts(MF("brother", "sister"));
    } else if (smaller <= 1 && delta <= 4) {
        switch (delta) {
            case 4: fputs("great-", stdout);
            case 3: fputs("great-", stdout);
            case 2: fputs("grand",  stdout);
        }
        if      (dist_a == 0) puts(MF("son",    "daughter"));
        else if (dist_b == 0) puts(MF("father", "mother"));
        else if (dist_a == 1) puts(MF("nephew", "niece"));
        else                  puts(MF("uncle",  "aunt"));
    } else if (smaller >= 2 && smaller <= 4 && delta <= 3) {
        if (delta == 0) printf("%s cousin\n", nth[smaller - 2]);
        else printf("%s cousin %s removed\n", nth[smaller - 2], removed[delta - 1]);
    } else {
        puts("kin");
    }
}

int main(int argc, char** argv) {
    int id_a, id_b;
    char sex;
    while (scanf("%d %d %c", &id_a, &id_b, &sex) && id_a >= 0) {
        handle_case(id_a, id_b, sex);
    }
    return 0;
}

B:二分答案

#include <math.h>
#include <stdio.h>

int main() {
    double pi = acos(-1);
    double precision = 0.00001 * pi / 180;
    double d, h, x, n1, n2;

    while (scanf("%lf %lf %lf %lf %lf", &d, &h, &x, &n1, &n2) && d) {
        double phi_min = 0;
        double phi_max = pi / 2;

        while (phi_max - phi_min > precision) {
            double phi = (phi_min + phi_max) / 2;
            double theta1 = pi / 2 - phi;
            double theta2 = asin(n2 * sin(theta1) / n1);

            if (d * tan(theta1) + h * tan(theta2) > x) {
                phi_min = phi;
            } else {
                phi_max = phi;
            }
        }

        printf("%0.02lf\n", phi_min * 180 / pi);
    }
}

暴力,注意字典序的排序方法以及字符串从1开始的递归终止条件是>长度 !!!!!

#include <bits/stdc++.h>
using namespace std;
char d[250][30],s[10][10];
int w,dd;char m[10][10];
int dir[8][2]={1,0,-1,0,0,1,0,-1,1,1,1,-1,-1,1,-1,-1};
struct Geng
{
    char s[30];
}ans[250];
bool cmp(Geng g1,Geng g2){
    int l = 0;
    for(int i = 0 ; g1.s[i] != '\0' && g2.s[i] != '\0' ; i++) {
        if(g1.s[i] != g2.s[i]) return g1.s[i] < g2.s[i];
        l = i;
    }
    int l1, l2;
    l1 = l2 = l + 1;
    if(g1.s[l + 1] != '\0') l1++;
    if(g2.s[l + 1] != '\0') l2++;
    return l1 < l2;
}
int find(char s[10][10],char *d,int x,int y,int pos){
    if(pos>strlen(d+1)){
        return 1;
    }
    char now=s[x][y];
    s[x][y]='0';
    for(int i=0;i<8;i++){
        int nx=x+dir[i][0];
        int ny=y+dir[i][1];
        if(s[nx][ny]=='q'){
            if(strlen(d+pos)>=2&&d[pos]=='q'&&d[pos+1]=='u'){
              if(find(s,d,nx,ny,pos+2)){
                  return 1;
              }  

            }
        }
            else if(s[nx][ny]==d[pos]){
                if(find(s,d,nx,ny,pos+1)){
                    return 1;
                }

            }
    }
    s[x][y]=now;
    return 0;
}
int main(){
    scanf("%d",&w);
        for(int i=1;i<=w;i++){
            scanf("%s",d[i]+1);
        }
    while(scanf("%d",&dd)!=EOF){
        if(dd==0) break;
        for(int i=0;i<=8;i++){
            for(int j=0;j<=8;j++){
                s[i][j]='0';
            }
        }
        for(int i=1;i<=dd;i++){
            scanf("%s",s[i]+1);
        }
        for(int i=1;i<=dd;i++){
            for(int j=1;j<=strlen(s[i]+1);j++){
                m[i][j]=s[i][j];
            }
        }
        int kk=0;
        for(int i=1;i<=w;i++){
            int flag=0;
            for(int j=1;j<=dd;j++){
                for(int k=1;k<=dd;k++){
                    if(s[j][k]=='q'){
                       if(strlen(d[i]+1)>=2&&d[i][1]=='q'&&d[i][2]=='u'){
                        for(int i1=1;i1<=dd;i1++){
                        for(int j1=1;j1<=strlen(s[i1]+1);j1++){
                            m[i1][j1]=s[i1][j1];
                            }
                        }
                         if(find(m,d[i],j,k,3)){
                            strcpy(ans[kk++].s,d[i]+1);flag=1;break;
                         }
                       }
                    }
                       else if(s[j][k]==d[i][1]){
                        for(int i1=1;i1<=dd;i1++){
                        for(int j1=1;j1<=strlen(s[i1]+1);j1++){
                        m[i1][j1]=s[i1][j1];
                            }
                                }
                        if(find(m,d[i],j,k,2)){
                            strcpy(ans[kk++].s,d[i]+1);flag=1;break;
                        }
                    }

                }
                if(flag) break;
            }
        }
//      for(int i = 0 ; i < kk ; i++) printf("%s\n", ans[i].s);
//      rp
        sort(ans,ans+kk,cmp);
        for(int i=0;i<kk;i++){
            printf("%s\n",ans[i].s);
        }
        puts("-");
    }
}
/*
1
rprquit
5
rprit
ahqln
ietep
zrysg
ogwey
0

*/

/**************************************************************
    Problem: 1719
    User: ALPC_t_1
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1508 kb
****************************************************************/

没想到这题用string写还是蛮方便的,直接暴力查询就好了,不用像char那样先匹配到一起,然后再整体比对,substr函数第一个是首指针,第二个是长度,可以直接取出来这个substr 判断是不是与字典相等即可~~

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 300;
const int MAXM = 1000 + 5;
int m;
string allot[MAXM];
map<char, string> ma;
char str1[MAXM];
string str2;
void init()
{
    ma.clear();
    for(int i = 0 ; i < 26 ; i++) {
        char u = i + 'A';
        scanf("%s", str1);
        cin>>str2;
        ma[u] = str2;
    }

    scanf("%d", &m);
    for(int i = 0 ; i < m ; i++) cin >> allot[i];
}
string data[MAXM];
string out[MAXM];
string match(string u)
{
    for(int i = 0 ; i < m ; i++) {
        int ok = 1;
        int now = 0;
        for(int j = 0 ; j < allot[i].size() ; j++) {
            int len = ma[allot[i][j]].size();
            if(u.substr(now, len) != ma[allot[i][j]]) {
                ok = 0;
                break;
            }
            else now += len;
            if(now > u.size()) {
                ok = 0;
                break;
            }
        }
        if(now != u.size()) ok = 0;
        if(ok == 1) return allot[i];
    }
    return "-1";
}
int main()
{
    init();
    int n;  
    while(scanf("%d", &n) != EOF && n) {
        int flag = 1;
        int pos;
        for(int i = 0 ; i < n ; i++) {
            cin >> data[i];
            out[i] = match(data[i]);
            if(out[i] == "-1") {
                if(flag == 1) {

                pos = i;
                flag = 0;
                }
            }
        }
        if(flag == 0) {
            cout << data[pos] << " not in dictionary.\n";
            continue;
        }
        for(int i = 0 ; i < n ; i++) {
            if(i) cout << " ";
            cout << out[i] ;
        }
        printf("\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值