GCJ2019 Round1C 题解

A.Robot Programming Strategy
就是看一下能不能干掉所有人,建个字典树,树上搜一下,如果再某一层有三种不同的情况那这棵子树就无解

#include<bits/stdc++.h>
using namespace std;
int hsh[27];
char rehsh[3];
struct node{
    int c[3];
    int su;
}tree[150000];
int cnt=0;
char str[550];
stack<int>ans;
void init(){
    memset(tree,0,sizeof tree);
    cnt=0;
    hsh['R'-'A']=0;rehsh[0]='R';
    hsh['P'-'A']=1;rehsh[1]='P';
    hsh['S'-'A']=2;rehsh[2]='S';
}
void Insert(int rt,int p){
    if(p==500)return;
    int q=hsh[str[p]-'A'];
    if(tree[rt].c[q]){
        Insert(tree[rt].c[q],p+1);
    }else{
        tree[rt].c[q]=++cnt;
        tree[rt].su++;
        Insert(cnt,p+1);
    }
}
int solve(int rt){
    if(tree[rt].su==1){
        for(int i=0;i<3;i++){
            if(tree[rt].c[i]){
               ans.push((i+1)%3);
            }
        }
        return 1;
    }
    else if(tree[rt].su==3){
        return 0;
    }
    else{
        for(int i=0;i<3;i++){
            int son=tree[rt].c[i];
            if(!son){
                int nxt=(i+2)%3;
                int ns=tree[rt].c[nxt];
                if(solve(ns)){
                    ans.push(nxt);
                    return 1;
                }
            }
        }
        return 0;
    }
}
int main(){

    int t;
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++){
        int n;
        init();
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",str);
            int len=strlen(str);
            for(int i=len;i<500;i++){
                str[i]=str[i-len];
            }
            str[500]=0;
            Insert(0,0);//puts("1");
        }
        printf("Case #%d: ",cas);
        if(!solve(0))puts("IMPOSSIBLE");
        else {
            while(!ans.empty()){
                printf("%c",rehsh[ans.top()]);
                ans.pop();
            }
            puts("");
        }

    }
    return 0;
}

B.Power Arrangers
交互题,思路很简单
5∗4∗3∗2∗1=1205*4*3*2*1=12054321=120
4∗3∗2∗1=244*3*2*1=244321=24
3∗2∗1=63*2*1=6321=6
2∗1=22*1=221=2
先扫第一位,找到不够的第一位的类,这类只有23个,以此类推

#include<bits/stdc++.h>
using namespace std;
vector<int>mv[5];
int ans[5];
int cnt=0;
int main(){

    int t,f;
    char str[3];
    scanf("%d%d",&t,&f);
    for(int cas=1;cas<=t;cas++){
        for(int i=0;i<5;i++)mv[i].clear();
        cnt=0;
        for(int i=0;i<119;i++){
            printf("%d\n",i*5+1);
            fflush(stdout);
            scanf("%s",str);
            int p=str[0]-'A';
            mv[p].push_back(i*5+1);
        }
        for(int i=0;i<5;i++){
            if(mv[i].size()==23){
                ans[cnt++]=i;
            }
            else mv[i].clear();
        }
//printf("ans[cnt]=%d\n",ans[cnt]);

        for(int i=0;i<23;i++){
            printf("%d\n",mv[ans[cnt-1]][i]+1);
            fflush(stdout);
            scanf("%s",str);
            int p=str[0]-'A';
            mv[p].push_back(mv[ans[cnt-1]][i]+1);
        }
        for(int i=0;i<5;i++){
            if(mv[i].size()==5){
                ans[cnt++]=i;
            }
            else mv[i].clear();
        }
//printf("ans[cnt]=%d\n",ans[cnt]);

        for(int i=0;i<5;i++){
            printf("%d\n",mv[ans[cnt-1]][i]+1);
            fflush(stdout);
            scanf("%s",str);
            int p=str[0]-'A';
            mv[p].push_back(mv[ans[cnt-1]][i]+1);
        }
        for(int i=0;i<5;i++){
            if(mv[i].size()==1){
                ans[cnt++]=i;
            }
            else mv[i].clear();
        }
///        printf("ans[cnt]=%d\n",ans[cnt]);
        for(int i=0;i<1;i++){
            printf("%d\n",mv[ans[cnt-1]][i]+1);
            fflush(stdout);
            scanf("%s",str);
            int p=str[0]-'A';
            mv[p].push_back(mv[ans[cnt-1]][i]+1);
        }mv[ans[cnt-1]].clear();
        for(int i=0;i<5;i++){
            if(mv[i].size()==1){
                ans[cnt++]=i;
            }
            else mv[i].clear();
        }
        int sum=10;
        for(int i=0;i<4;i++){
            sum-=ans[i];
            //printf("%d\n",ans[i]);
        }
        ans[4]=sum;
        swap(ans[4],ans[3]);

        for(int i=0;i<5;i++){
            printf("%c",ans[i]+'A');
        }puts("");

        fflush(stdout);
        scanf("%s",str);
        if(str[0]=='Y')continue;
        else break;
    }
    return 0;
}

C不会,待补

c++14 # P13476 [GCJ 2008 APAC SemiFinal] Millionaire ## 题目描述 你受邀参加了著名电视节目“你想成为百万富翁吗?”。当然你想! 游戏规则很简单: - 在游戏开始前,主持人会转动幸运轮,决定每次下注获胜的概率 $P$。 - 你起始拥有 $X$ 美元。 - 游戏共进行 $M$ 轮下注。在每一轮中,你可以下注当前所拥有金额的任意部分,包括全部或不下注。下注金额可以不是整数。 - 如果你赢得本轮下注,你的总金额会增加你下注的金额;如果你输掉本轮下注,你的总金额会减少你下注的金额。 - 所有下注结束后,如果你累计金额达到 $1000000$ 或以上,你可以保留你的奖金(这时金额向下取整为整数美元);否则你将一无所获。 给定 $M$、$P$ 和 $X$,请你计算在最优策略下(即最大化成为百万富翁概率的策略),你成为百万富翁的概率。 ## 输入格式 输入的第一行是测试用例数 $N$。 接下来的 $N$ 行,每行格式为 “$M$ $P$ $X$”,其中: - $M$ 为整数,表示下注轮数。 - $P$ 为实数,表示每轮下注获胜的概率。 - $X$ 为整数,表示初始金额(美元)。 ## 输出格式 对于每个测试用例,输出一行,格式为 “Case #$X$: $Y$”,其中: - $X$ 为测试用例编号,从 $1$ 开始。 - $Y$ 为成为百万富翁的概率,范围在 $0$ 到 $1$ 之间。 当你的答案的绝对误差或相对误差不超过 $10^{-6}$ 时,将被视为正确。 ## 输入输出样例 #1 ### 输入 #1 ``` 2 1 0.5 500000 3 0.75 600000 ``` ### 输出 #1 ``` Case #1: 0.500000 Case #2: 0.843750 ``` ## 说明/提示 **样例解释** 在第一个样例中,唯一能达到 $1000000$ 的方式是在唯一一轮中押上全部金额。 在第二个样例中,你可以通过合理下注,即使输掉一轮也有机会成为百万富翁。以下是一种下注方式: - 第一轮你有 \$600000,下注 \$150000。 - 如果第一轮输了,你剩下 \$450000,下注 \$100000。 - 如果第一轮输了、第二轮赢了,你有 \$550000,下注 \$450000。 - 如果第一轮赢了,你有 \$750000,下注 \$250000。 - 如果第一轮赢了、第二轮输了,你有 \$500000,下注 \$500000。 **数据范围** - $1 \leq N \leq 100$ - $0 \leq P \leq 1.0$,小数点后最多 6 位 - $1 \leq X \leq 1000000$ **小数据集(13 分,测试点 1 - 可见)** - $1 \leq M \leq 5$ **大数据集(16 分,测试点 2 - 隐藏)** - $1 \leq M \leq 15$ 由 ChatGPT 4.1 翻译
最新发布
12-20
c++14 ## 题目描述 你正在观看体育史上最重要的一场比赛:Oceania Coders 队对阵 Eurasia Jammers 队,比赛场地为 Centrifugal Bumble-Puppy 世界总决赛。不幸的是,由于你因期待而彻夜难眠,比赛期间你竟然睡着了! 现在计分牌上显示着双方的得分,可能带有一个或多个前导零(因为计分牌会显示固定位数的数字)。当你熟睡时,计分牌的一些灯泡被猛烈的球击坏了,因此一方或双方的得分中有一位或多位数字没有显示出来。 你觉得比分接近的比赛最精彩,所以你希望能够想象出一个比分尽可能接近的场景。你能否用某种方式填补所有缺失的数字,使得两队分数的绝对差值最小?如果有多种方案可以达到最小绝对差值,请选择 Coders 队得分最小的方案;如果在 Coders 队得分也相同的情况下仍有多种方案,则选择 Jammers 队得分最小的方案。 ## 输入格式 输入的第一行包含一个整数 $\mathbf{T}$,表示测试用例数量。接下来有 $\mathbf{T}$ 组测试用例。每组测试用例包含一行,包含两个非空字符串 $\mathbf{C}$ 和 $\mathbf{J}$,长度相同,仅由十进制数字和问号组成,分别表示你看到的 Coders 队和 Jammers 队的分数。每组测试用例中至少有一个问号。 ## 输出格式 对于每组测试用例,输出一行 `Case #x: c j`,其中 $x$ 为测试用例编号(从 1 开始),$c$ 是将 $\mathbf{C}$ 中所有问号替换为数字后的结果,$j$ 是将 $\mathbf{J}$ 中所有问号替换为数字后的结果,使得 $c$ 和 $j$ 所表示的整数的绝对差值最小。如果有多个解的绝对差值相同,选择 $c$ 最小的解;如果 $c$ 也相同,则选择 $j$ 最小的解。 ## 输入输出样例 #1 ### 输入 #1 ``` 4 1? 2? ?2? ??3 ? ? ?5 ?0 ``` ### 输出 #1 ``` Case #1: 19 20 Case #2: 023 023 Case #3: 0 0 Case #4: 05 00 ``` ## 说明/提示 **样例解释** 在样例第 4 组中,注意答案不能是 15 10;该方案虽然绝对差值最小,但 Coders 队得分不是最小的。也不能是 05 10;该方案虽然绝对差值和 Coders 队得分都最小,但 Jammers 队得分不是最小的。 **限制条件** - $1 \leqslant \mathbf{T} \leqslant 200$。 - $\mathbf{C}$ 和 $\mathbf{J}$ 长度相同。 **小数据集(测试集 1 - 可见)** - $1 \leqslant \mathbf{C}$ 和 $\mathbf{J}$ 的长度 $\leqslant 3$。 **大数据集(测试集 2 - 隐藏)** - $1 \leqslant \mathbf{C}$ 和 $\mathbf{J}$ 的长度 $\leqslant 18$。
12-09
请使用c++解决以下问题: ## 题目描述 你是歌剧中的一个小角色——塞维利亚的园丁。歌剧的舞台背景是一个由单位格组成的矩形庭院,共有 $\mathbf{R}$ 行 $\mathbf{C}$ 列。你被要求在庭院中布置一组树篱迷宫:每个格子都必须放置一根对角树篱。对于任意一个格子,有两种可能的树篱类型:从左下到右上(用 `/` 表示),或从左上到右下(用 `\` 表示)。任何相邻的树篱相接处都会形成一堵连续的墙。 庭院外围有一圈单位格,宽度为一格,四个角格子缺失。每一个外围格子里都住着一位廷臣。外围格子的编号顺时针排列,从顶行最左侧的格子编号为 1,最后一个编号为 $2 \times (\mathbf{R}+\mathbf{C})$,即左列最顶端的格子。例如,当 $\mathbf{R}=2, \mathbf{C}=2$ 时,外围格子的编号如下(注意,此时还未放置树篱): ``` 12 8 3 7 4 65 ``` 在这个与众不同的歌剧中,爱情是互相且唯一的:每位廷臣只爱一位其他廷臣,且这份爱是双向且专属的。每位廷臣都希望能穿越树篱迷宫,悄悄地与心上人相会,并且不被其他廷臣遇见。也就是说,任意一对恋人廷臣之间,必须存在一条只属于他们两人的、被树篱墙与其他路径完全隔开的通路。迷宫中可以存在不属于任何廷臣路径的部分,只要所有恋人对都能连通即可。 给定所有恋人配对关系,你能否构造出这样一组树篱迷宫,使得每一对恋人都能连通?如无法实现,请输出 IMPOSSIBLE。 ## 输入格式 输入的第一行包含一个整数 $\mathbf{T}$,表示测试用例组数。接下来有 $\mathbf{T}$ 组测试用例,每组包含两行。第一行为两个整数 $\mathbf{R}$ 和 $\mathbf{C}$,表示庭院的行数和列数。第二行为一个长度为 $2 \times (\mathbf{R}+\mathbf{C})$ 的排列,包含所有廷臣的编号。第 1、2 个编号为一对恋人,第 3、4 个编号为一对恋人,以此类推。 ## 输出格式 对于每组测试用例,先输出一行 `Case #x:`,其中 $x$ 为测试用例编号(从 1 开始)。如果无法满足条件,再输出一行 IMPOSSIBLE。否则,输出 $\mathbf{R}$ 行,每行 $\mathbf{C}$ 个字符,表示一个合法的树篱迷宫,每个字符为 `/` 或 `\`。迷宫中的每个格子都必须填满,不能留空。若存在多种方案,你可任选其一输出。 ## 输入输出样例 #1 ### 输入 #1 ``` 4 1 1 1 4 3 2 1 3 1 8 2 7 3 4 5 6 2 2 8 1 4 5 2 3 7 6 1 1 1 3 2 4 ``` ### 输出 #1 ``` Case #1: / Case #2: //\ Case #3: // \/ Case #4: IMPOSSIBLE ``` ## 说明/提示 **样例解释** 在第 3 组中,恋人配对为 $(8, 1), (4, 5), (2, 3), (7, 6)$。如下是样例输出的示意图: ![](https://cdn.luogu.com.cn/upload/image_hosting/bxa3n9a8.png) 对于第 3 组,下面这种迷宫也是合法的: ``` /\ \/ ``` 在第 4 组中,庭院仅有一个格子,外围廷臣编号按顺时针分别为 1、2、3、4。此时只有两种放置方式:/ 或 \。第一种会形成 1 到 4、2 到 3 的通路,第二种会形成 1 到 2、3 到 4 的通路。但本组数据中 1 爱 3、2 爱 4,无论哪种方式都无法满足条件,因此输出 IMPOSSIBLE,歌剧中将充满悲伤的咏叹调! **限制条件** **小数据集(6 分,测试集 1 - 可见)** - $1 \leqslant \mathbf{T} \leqslant 100$。 - $1 \leqslant \mathbf{R} \times \mathbf{C} \leqslant 16$。 **大数据集(23 分,测试集 2 - 隐藏)** - $1 \leqslant \mathbf{T} \leqslant 500$。 - $1 \leqslant \mathbf{R} \times \mathbf{C} \leqslant 100$。
11-06
### 解题思路分析 P13288 [GCJ 2013 #1B] Osmos 是一道模拟类题目,其核心在于理解如何通过一个“吞噬”机制让主角 Armin 的质子尽可能多地吸收其他质子。题目要求的是在给定初始质量与一系列其他质子的质量的前提下,计算 Armin 可以吸收的最大质子数量。 #### 问题建模 Armin 起始有一个质量为 $ A $ 的质子。如果某个质子的质量小于当前 Armin 的质子质量,则可以被吸收,并增加 Armin 的质子质量(新的质量等于两者的总和)。否则,无法吸收该质子。 可以通过贪心策略来解决这个问题: - 首先将所有质子按照质量从小到大排序。 - 然后尝试依次吸收每一个质子。如果当前质子的质量小于 Armin 的质子质量,则将其吸收;否则跳过。 - 如果无法吸收当前质子,可以考虑添加一个新的质子(质量小于当前 Armin 的质子质量),使得 Armin 的质子质量增加,从而能够继续吸收更大的质子。这一步需要动态调整,确保新增的质子质量最小且有效。 #### 核心算法 使用贪心策略结合排序: 1. 将所有质子按质量升序排列。 2. 使用循环遍历质子列表,判断是否可以吸收当前质子。 3. 如果不能吸收,则不断添加新的质子(质量为当前 Armin 的质子质量 - 1),直到能够吸收下一个质子。 4. 统计最终能够吸收的质子总数。 ### 示例代码实现 以下是基于上述解题思路的 Python 实现示例: ```python def solve_osmos(): import sys input = sys.stdin.read data = input().split() T = int(data[0]) index = 1 results = [] for case in range(1, T + 1): A = int(data[index]) N = int(data[index + 1]) masses = list(map(int, data[index + 2:index + 2 + N])) index += 2 + N masses.sort() added = 0 absorbed = 0 current_mass = A i = 0 while i < N: if current_mass > masses[i]: current_mass += masses[i] absorbed += 1 i += 1 else: # Add a new proton with mass (current_mass - 1) if current_mass > 1: current_mass += current_mass - 1 added += 1 else: # Cannot add any more protons break results.append(f"Case #{case}: {absorbed + added}") for res in results: print(res) ``` ### 复杂度分析 - **时间复杂度**:排序操作的时间复杂度为 $ O(N \log N) $,其中 $ N $ 是质子的数量。后续的遍历操作是线性的 $ O(N) $,因此整体时间复杂度为 $ O(N \log N) $。 - **空间复杂度**:额外空间主要用于存储质子质量列表,因此空间复杂度为 $ O(N) $。 ### 关键点总结 - 排序是解决问题的第一步,确保从小到大地处理每个质子。 - 在无法吸收当前质子时,贪心地选择添加最小可能质量的质子,以确保效率最大化。 - 注意边界条件,例如当 Armin 的质子质量为 1 时,无法通过添加新质子来提升质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值