首页 PAT-Be Unique & String Subtraction & Find Coins & Mooncake & Magic Coupon & Sort with Swap(0, i)
文章
取消

PAT-Be Unique & String Subtraction & Find Coins & Mooncake & Magic Coupon & Sort with Swap(0, i)

A1041 Be Unique

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;

int main()
{
    unordered_map<int, int> map;
    int N;//数字个数
    cin >> N;
    vector<int> nums;//按顺序储存所有的数字
    for (int i = 0; i < N; i++)
    {
        int num;
        cin >> num;
        if (!map.count(num))//如果之前没遇到过num
        {
            nums.emplace_back(num);
        }
        map[num]++;
    }
    for (int n : nums)
    {
        if (map[n] == 1)
        {
            cout << n;
            return 0;
        }
    }
    cout << "None";
    return 0;
}

    简单题,不多解释。

A1050 String Subtraction

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
#include<string>
#include<unordered_map>
using namespace std;

int main()
{
    unordered_map<char, int> map;
    string s1, s2;
    getline(cin, s1);
    getline(cin, s2);
    for (char c : s2)
    {
        map[c]++;
    }
    for (char c : s1)
    {
        if (!map.count(c))
        {
            cout << c;
        }
    }
}

    简单的哈希表

A1048 Find Coins

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include<iostream>
#include<string>
#include<unordered_map>
#include<set>
using namespace std;

int main()
{
    int N, M;//硬币数、金额
    cin >> N >> M;
    unordered_map<int, int> coinMap;
    set<int> coinKind;
    for (int i = 0; i < N; i++)
    {
        int _coin;
        cin >> _coin;
        coinKind.insert(_coin);
        coinMap[_coin]++;
    }
    for (auto c : coinKind)
    {
        if (2 * c > M) break;//如果c大于M的一半,直接退出循环
        else if (2 * c == M)//如果c是M的一半
        {
            if (coinMap[c] >= 2)
            {
                cout << c << ' ' << M - c;
                return 0;
            }
        }
        else if (coinMap.count(M - c))
        {
            cout << c << ' ' << M - c;
            return 0;
        }
    }
    cout << "No Solution";
    return 0;
}

    这道题有个小陷阱,就是使用的硬币V1得<=V2,其中如果等于的话,得看map里有没有两个等面值的硬币。

A1070 Mooncake

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct mooncake
{
    double inventory;//库存
    double totalPrice;//总价
    double price;//单价
    mooncake(double _inventory) :inventory(_inventory) {}
};
bool comp(mooncake& c1, mooncake& c2)
{
    return c1.price > c2.price;
}
int main()
{
    int N, D;//月饼种类、超商需求
    cin >> N >> D;
    double demand = (double)D;
    vector<mooncake> cakes;
    //读取每种月饼的库存
    for (int i = 0; i < N; i++)
    {
        double _inventory;
        cin >> _inventory;
        cakes.emplace_back(mooncake(_inventory));
    }
    for (int i = 0; i < N; i++)
    {
        double _price;
        cin >> _price;
        cakes[i].totalPrice = _price;
        cakes[i].price = _price / cakes[i].inventory;
    }
    //按价位排序
    sort(cakes.begin(), cakes.end(), comp);
    double profit = 0.0;
    for (auto c : cakes)
    {
        if (c.inventory < demand)//如果当前种类月饼的库存小于需求,那么全买
        {
            profit += c.totalPrice;
            demand -= c.inventory;
        }
        else if (c.inventory == demand)//如果当前种类月饼的库存等于需求,也全买并且退出
        {
            profit += c.totalPrice;
            break;
        }
        else//如果当前种类月饼的库存大于需求,只买一部分并且退出
        {
            profit += ((double)demand / (double)c.inventory * c.totalPrice);
            break;
        }
    }
    printf("%.2lf", profit);
}

    这道题,外表看似简单,其实隐藏了一个惊天大陷阱。注意input Specification中是这么讲的:the first line contains 2 positive integers;Then the second line gives the positive inventory amounts,这后面的库存其实只是正数,没说不能是小数,所以如果都按整型来算,是会有一个测试点过不去的,岂可休!

A1037 Magic Coupon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

bool comp1(int a, int b)//从大到小排序
{
    return a > b;
}
int main()
{
    int nC, nP;//优惠券数量,产品数量
    vector<int> couponPostive, couponNegtive;//分别储存正、负优惠券
    vector<int> productPostive, productNegtive;//分别储存正、负产品
    cin >> nC;
    while (nC--)
    {
        int c;
        cin >> c;
        //只考虑正负,不考虑0
        if (c > 0) couponPostive.emplace_back(c);
        else if (c < 0) couponNegtive.emplace_back(c);
    }
    cin >> nP;
    while (nP--)
    {
        int p;
        cin >> p;
        if (p > 0) productPostive.emplace_back(p);
        else if (p < 0) productNegtive.emplace_back(p);
    }
    //给正数数组按从大到小排序
    sort(couponPostive.begin(), couponPostive.end(), comp1);
    sort(productPostive.begin(), productPostive.end(), comp1);
    //给负数数组按从小到大排序
    sort(couponNegtive.begin(), couponNegtive.end());
    sort(productNegtive.begin(), productNegtive.end());
    int maximum = 0;
    //计算正数中的最大收益
    //取二者小的
    int len = couponPostive.size() < productPostive.size() ? couponPostive.size() : productPostive.size();
    for (int i = 0; i < len; i++)
    {
        maximum += (couponPostive[i] * productPostive[i]);
    }
    //同样取二者小的
    len = couponNegtive.size() < productNegtive.size() ? couponNegtive.size() : productNegtive.size();
    for (int i = 0; i < len; i++)
    {
        maximum += (couponNegtive[i] * productNegtive[i]);
    }
    cout << maximum;
}

    简单的贪心算法。

A1067 Sort with Swap(0, i)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int main()
{
    int N;//序列长度
    cin >> N;
    vector<int> pos(N);
    //记录每个数字的位置
    int mismatch = 0;//不在本位个数(除了0)
    for (int i = 0; i < N; i++)
    {
        int _num;
        cin >> _num;
        pos[_num] = i;
        if (pos[_num] != _num && _num != 0)//统计有多少个数(除了0)不在本位
        {
            mismatch++;
        }
    }
    //贪心算法,硬贪,先判断0在不在0位上,不在的话就直接交换,
    //在的话就跟第一个不在本位的数字交换后再换
    int ans = 0;
    int k = 1;//记录不在本位数字的最小下标/位置
    while (mismatch > 0)//还有数字不在本位
    {
        //如果0在位置0
        if (pos[0] == 0)
        {
            //那么去找一个不在本位的数字,和它交换位置
            while (k < N && pos[k] == k)
            {
                k++;
            }
            swap(pos[0], pos[k]);//0和k的位置互换
            ans++;
        }
        while (pos[0] != 0)//如果0不在位置0
        {
            //正常交换
            swap(pos[0], pos[pos[0]]);
            ans++;
            mismatch--;
        }
    }
    cout << ans;
}

    这道题,说实话,有点小难,虽然我想到了这个策略,但我觉得并不一定真的是最优的策略,就止步不前了,没想到还就是这么个策略,看来贪心算法真是要有胆量去做。

    直接默认如果0到了0位却还没有都归位,那就让0和最邻近的一个没归位的数交换位置。

本文由作者按照 CC BY 4.0 进行授权