UVA - 11264 Coin Collector (贪心) (day_8_H)

本文探讨了一个有趣的算法问题,即如何通过最优策略在一次取款中收集最多种类的硬币。通过分析银行的取款算法,我们找到了一种贪心策略来最大化不同硬币的收集数量。

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

Coin Collector

Our dear Sultan is visiting a country where there are n different types of coin. He wants to collect
as many different types of coin as you can. Now if he wants to withdraw X amount of money from a
Bank, the Bank will give him this money using following algorithm.
withdraw(X){
if( X == 0) return;
Let Y be the highest valued coin that does not exceed X.
Give the customer Y valued coin.
withdraw(X-Y);
}
Now Sultan can withdraw any amount of money from the Bank. He should maximize the number
of different coins that he can collect in a single withdrawal.
Input
First line of the input contains T the number of test cases. Each of the test cases starts with n
(1 ≤ n ≤ 1000), the number of different types of coin. Next line contains n integers C1, C2, . . . , Cn
the value of each coin type. C1 < C2 < C3 < . . . < Cn < 1000000000. C1 equals to 1.
Output
For each test case output one line denoting the maximum number of coins that Sultan can collect in a
single withdrawal. He can withdraw infinite amount of money from the Bank.
Sample Input
2
6
1 2 4 8 16 32
6
1 3 6 8 15 20
Sample Output
6
4

题目简述:

苏丹要用钱换硬币,硬币有非常多种,苏丹想要尽可能多种类的硬币。规则是:换硬币时优先给你小于等于总金额的面额最大的硬币。

题目分析:

找好贪心策略很关键。
这位博主讲解的非常清楚:https://blog.youkuaiyun.com/synapse7/article/details/12262029

代码实现:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
#include<cstdlib>
#include<cmath>
#include<queue>
//#include <bits/stdc++.h>
using namespace std;

const int INF = 0x3f3f3f3f;
#define pf          printf
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define ms(i,j) memset(i,j,sizeof(i))

int a[1005];
int main()
{
    int T,n;
    sf(T);
    while(T--)
    {
        int sum=0,s=0;
        sf(n);
        for(int i=1;i<=n;i++)
            sf(a[i]);
        for(int i=1;i<n;i++)
        {
            if(sum<a[i]&&sum+a[i]<a[i+1])
            {
                sum+=a[i];
                s++;
            }
        }
        pf("%d\n",s+1);
    }
}
<think>好的,我现在需要帮助用户解决如何用awk提取他们提供的特定格式的数据。首先,我得仔细看看用户的问题。他们给出的示例数据是一行键值对,用空格分隔,例如“uid:364220338356480 day_bet:1742600”等等。用户想知道如何用awk提取每个字段的值。 首先,我需要回忆一下awk的基本用法。awk默认是按空格或制表符分割每行的字段,但在这个例子中,每个字段本身是“key:value”的形式,所以直接使用默认的分隔符可能不太行,因为每个键值对会被当作一个字段。比如,“uid:364220338356480”会被视为一个字段,而“day_bet:1742600”是另一个字段,这样用户可能希望将每个键值对分开,然后提取其中的值。 用户可能的目标是提取每个冒号后面的数值部分。例如,从“uid:364220338356480”中提取“364220338356480”,从“day_bet:1742600”中提取“1742600”等等。所以,问题在于如何分割每个键值对,并取出值部分。 这时候,我应该考虑修改awk的字段分隔符。默认的字段分隔符是空格,但如果将分隔符设置为“:”或者同时考虑空格和冒号,可能会更有效。不过,这里每个键值对之间是用空格分隔的,而键和值之间用冒号分隔。所以,可能的策略是先按空格分割得到每个键值对,然后再对每个键值对按冒号分割,取出值部分。 例如,对于第一个字段“uid:364220338356480”,使用split函数将其分割成键和值。或者,可以将整个行的字段分隔符设置为“:”,但这样可能会导致每个键值对的分割出现问题,因为每个键值对内部有一个冒号,而它们之间是用空格分隔的。 或者,可以将字段分隔符设置为空格或冒号,使用正则表达式作为分隔符。例如,设置-F'[ :]+',这样awk会将空格或冒号视为分隔符,但这样可能会导致键和值被分开。例如,“uid:364220338356480”会被分割成“uid”和“364220338356480”,然后下一个键值对“day_bet:1742600”会被分割成“day_bet”和“1742600”,依此类推。这样,每个键后面跟着的值会成为单独的字段,但需要确定如何配对键和值。 不过,这种情况下,每两个字段可能组成一个键值对。例如,第一个字段是键,第二个是值,第三个是下一个键,第四个是下一个值,以此类推。但用户的数据中每个键值对是连续的,没有空格,所以可能需要另一种方法。 或者,可以先将每行的字段分隔符设置为空格,这样每个键值对是一个字段,然后对每个字段进行处理,分割出值。例如,对于每个字段(如$1是“uid:364220338356480”,$2是“day_bet:1742600”等),使用substr或split函数来提取值部分。 例如,对于每个字段,使用split($i, arr, ":"),这样arr[2]就是值。然后遍历所有字段,提取每个键值对的值。 因此,具体的步骤可能是: 1. 设置字段分隔符为空格,这样每个键值对是一个字段。 2. 遍历每个字段,对每个字段使用split函数按冒号分割,取第二个元素作为值。 3. 输出所有值,或者根据需求输出特定键的值。 用户可能需要将所有值提取出来,或者根据键名提取对应的值。比如,用户可能想要提取uid的值,或者day_bet的值等等。 根据用户提供的示例数据,可能的命令是: awk '{for(i=1;i<=NF;i++){split($i,a,":"); print a[2]}}' filename 这会遍历每个字段,分割每个字段成键和值,然后打印值部分。这样输出会是每个值一行,可能不太方便。或者,用户可能希望将所有值输出为一行,用空格分隔,或者以其他方式。 如果用户想要针对特定的键提取值,比如提取uid的值,可以使用类似: awk '{for(i=1;i<=NF;i++){split($i,a,":"); if(a[1]=="uid") print a[2]}}' filename 但需要注意,如果字段顺序不固定,这种方法可能需要遍历所有字段直到找到对应的键。 回到用户的问题,他们可能想要提取每个字段的值,也就是每个键对应的数值。因此,正确的做法是将每个键值对分割成键和值,然后提取值部分。 可能的awk命令是: awk -F'[ :]+' '{for(i=2;i<=NF;i+=2) print $i}' 这里,将分隔符设置为空格或冒号(正则表达式[ :]+),这样每个键会被视为奇数位置的字段,值在偶数位置。然后循环从i=2开始,每隔一个字段取一个值。例如,对于“uid:364220338356480 day_bet:1742600”,分割后的字段是“uid”、“364220338356480”、“day_bet”、“1742600”等等。所以,i从2开始,每次增加2,就能取到所有的值。然后打印这些值。 不过,这种方法可能存在问题,比如如果某个值本身包含冒号,例如“note:abc:123”,这时候分割会出错。不过根据用户提供的数据示例,值都是数字,所以可能没问题。 另一种方法是,将每个字段按冒号分割一次,取第二部分。例如: awk '{for(i=1;i<=NF;i++){print split($i,a,":")?a[2]:""}}' 或者更简洁的: awk '{for(i=1;i<=NF;i++){print substr($i, index($i,":")+1)}}' 这会找到每个字段中冒号的位置,然后截取冒号后面的部分作为值。 这种方法可能更可靠,因为它直接取冒号后的内容,不管是否有多个冒号,但用户的数据中可能每个键值对只有一个冒号。 因此,综合来看,用户可能需要两种方法之一:一种是修改字段分隔符,然后按奇偶位置取数值;另一种是遍历每个字段,分割冒号后的值。 现在需要根据用户的具体需求来决定。如果用户只需要提取所有值,不管对应的键,那么第一种方法可能更高效。如果用户需要根据键名提取对应的值,那么需要遍历每个字段,分割键和值,然后判断键名。 用户的问题中,给出的示例数据是类似“uid:364220338356480 day_bet:1742600”这样的行,需要提取每个字段的值。可能的命令是: awk '{for(i=1; i<=NF; i++) {split($i, a, ":"); print a[2]}}' filename 这样会将每个键值对的值单独打印出来,每个值一行。如果用户希望结果以行显示,所有值在同一行,可以用: awk '{for(i=1; i<=NF; i++) {split($i, a, ":"); printf "%s ", a[2]}; print ""}' filename 或者,如果用户想要以逗号分隔或其他格式输出。 另外,用户可能需要将每个值赋给变量,或者进行其他处理,但根据问题描述,用户可能只需要提取值部分。 此外,需要注意原数据中的分隔符是否是空格。例如,在示例数据中,键值对之间是否有多个空格,或者是否有制表符。如果分隔符不是空格,可能需要调整字段分隔符,比如使用-F'[ \t]+'来匹配多个空格或制表符。 总结来说,用户的问题可以通过将每个键值对视为一个字段,分割出冒号后的值来解决。具体实现可以是遍历每个字段,使用split函数分割冒号,然后取出第二部分。</think>你可以通过 `awk` 按 `key:value` 格式提取每个字段的值。以下是具体方法: --- ### **1. 提取单个字段的值** 假设要提取 `uid` 对应的值 `364220338356480`: ```bash awk '{for(i=1; i<=NF; i++) {split($i, a, ":"); if(a[1]=="uid") print a[2]}}' 文件名 ``` **输出**: ``` 364220338356480 ``` --- ### **2. 提取所有字段的值** #### **(1)逐行输出所有值** ```bash awk '{for(i=1; i<=NF; i++) {split($i, a, ":"); print a[2]}}' 文件名 ``` **输出**(每行一个值): ``` 364220338356480 1742600 1751700 -52665 ... ``` #### **(2)单行输出所有值(空格分隔)** ```bash awk '{for(i=1; i<=NF; i++) {split($i, a, ":"); printf "%s ", a[2]}; print ""}' 文件名 ``` **输出**: ``` 364220338356480 1742600 1751700 -52665 1212 1212 4379 250 20000 966166511339180035 16 ``` --- ### **3. 提取特定字段的值(按列名)** 若需提取多个字段(如 `uid` 和 `bet`): ```bash awk '{ delete values; # 清空数组 for(i=1; i<=NF; i++) { split($i, a, ":"); values[a[1]] = a[2] # 存储为键值对 } print values["uid"], values["bet"] }' 文件名 ``` **输出**: ``` 364220338356480 250 ``` --- ### **4. 结合列名与值的完整映射** 生成所有字段的 `key:value` 映射: ```bash awk '{ for(i=1; i<=NF; i++) { split($i, a, ":"); printf "%s=%s ", a[1], a[2] } print "" }' 文件名 ``` **输出**: ``` uid=364220338356480 day_bet=1742600 day_win=1751700 extra_profit=-52665 prop=1212 new_prop=1212 ran=4379 bet=250 coin=20000 id=966166511339180035 fish_id=16 ``` --- ### **关键点** 1. **字段分割逻辑**: - `split($i, a, ":")`:将第 `i` 个字段按 `:` 分割,结果存入数组 `a`。 - `a[1]` 是字段名(如 `uid`),`a[2]` 是对应的值。 2. **灵活遍历**:通过 `for` 循环遍历所有字段(`NF` 表示总字段数)。 3. **动态存储**:可将值存入关联数组(如 `values[key]`),便于按需访问。 --- ### **应用场景** - **日志分析**:快速提取日志中的关键数值(如 `bet`、`coin`)。 - **数据转换**:将 `key:value` 格式转换为 CSV/表格。 - **动态筛选**:根据字段名提取值,避免依赖固定列位置。 --- ### **注意事项** - **字段顺序无关性**:通过键名(如 `uid`)提取值,即使字段顺序变化也能正确获取。 - **特殊字符处理**:若值包含 `:` 或空格,需确保数据格式严格分隔(如用 `\t` 代替空格)。 - **多行处理**:若文件有多行数据,上述命令会逐行处理。 --- ### **完整示例** 假设文件 `data.txt` 包含以下内容: ``` uid:364220338356480 day_bet:1742600 day_win:1751700 extra_profit:-52665 prop:1212 new_prop:1212 ran:4379 bet:250 coin:20000 id:966166511339180035 fish_id:16 ``` 运行命令: ```bash awk '{ for(i=1; i<=NF; i++) { split($i, a, ":"); printf "%s=%s\n", a[1], a[2] } }' data.txt ``` **输出**: ``` uid=364220338356480 day_bet=1742600 day_win=1751700 extra_profit=-52665 prop=1212 new_prop=1212 ran=4379 bet=250 coin=20000 id=966166511339180035 fish_id=16 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值