2018-03-15 <map> 刷题

map 模板类

#include <map> 
#include <string>
#include <cstdlib>
#include <iostream>

using namespace std;

int main(){

定义一个 map,Key 为字符串,Value 为整数。(想用CString,似乎只有 MFC 才有这个)

    typedef map<string, int> str_int_map;
    str_int_map myMap;

插入键值对有三种方法。

  • 用 insert 时,插入 Key 的已有,则插入失败,可以用其返回的 pair<str_int_map::iterator, bool> 来查看插入是否成功。pair 的第一个变量是一个 map 的迭代器,第二个变量是 bool,如果插入成功 .second 为真。

  • 用方括号(有点像 py)时,如果 Key 已有则新的值会覆盖旧的值。

    pair<str_int_map::iterator, bool> insert_pair;

    insert_pair = myMap.insert(pair<string, int>("drei", 3)); cout << insert_pair.second << endl;
    insert_pair = myMap.insert(pair<string, int>("vier", 4)); cout << insert_pair.second << endl;

    insert_pair = myMap.insert(str_int_map::value_type("eins", 1)); cout << insert_pair.second << endl;
    insert_pair = myMap.insert(str_int_map::value_type("zwei", 2)); cout << insert_pair.second << endl;

    myMap["funf"] = 5;
    myMap["sechs"] = 6;

看大小用 size()。

    cout << "myMap.size = " << myMap.size() << endl;

遍历用迭代器, begin(), end(), rbegin(), rend(), ++

    str_int_map::iterator iter;
    for(iter = myMap.begin(); iter != myMap.end(); iter ++){
        cout << iter->first << " " << iter->second << '\n';
    }

    str_int_map::reverse_iterator riter;
    for(riter = myMap.rbegin(); riter != myMap.rend(); riter ++){
        cout << riter->first << " " << riter->second << '\n';
    }

根据 Key 查找 Value 用 find()。用 Key 填进中括号好像也行。如果查不到,返回 end() 的值。

    cout << myMap["zwei"] << endl;
    str_int_map::iterator iterf = myMap.find("funf");
    if(iterf != myMap.end()) cout << "Find funf = " << iterf->second << endl; else cout << "Not found\n";

删除用 erase(), 参数可以传:

  • iterator erase(iterator it);//通过一个条目对象删除
  • iterator erase(iterator first,iterator last)//删除一个范围
  • size_type erase(const Key&key);//通过关键字删除

clear()就相当于enumMap.erase(enumMap.begin(),enumMap.end());

删掉它:

    myMap.erase(iterf);

然后就找不到啦,会返回 end():

    iterf = myMap.find("funf");
    if(iterf != myMap.end()) cout << "Find funf = " << iterf->second << endl; else cout << "Not found\n";

over:

    system("pause");
    return 0;
}

map 是一棵红!黑!树!就是最不会写的那种树!就是上次考试时用了能多赚一个 case 的那棵树!是不是很想把各种奇葩数据都搞成结构体然后存进去,就可以为所欲为了~

map 中的元素是自动按 Key 升序排序,默认是采用小于号来排序的,所以自己的类型得重载一下 < ……啊重载函数怎么写的来着……之后遇到题的话再写一下吧……

1071 SpeechPatterns 字符串 map/hash

找出现次数最多的单词。

因为实在没有思路,感觉自己写一定超时,只好学了一下 map。

后来还是超时了,是因为我刚开始把字符全都读进了大数组,然后一个一个挑。后来想起来可以直接 getchar()。刚开始我还把临时组成的单词存在 char[] 里,然后再转换成 string,也是够呛的。后来这些都改掉,就过啦。

写出来的 c和 c++的混血儿也是够呛的:

# include <string>
# include <map>
# include <cstdio>
# include <cstring>
# include <iostream>

using namespace std;

typedef map<string, int> str_int_map;

char c;
string w;

int main() {
    str_int_map myMap;

    while((c = getchar()) != '\n') {
        if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) {
            w += c; //string 可以 += ,相当于 strcat
        }
        else if (c >= 'A' && c <= 'Z') { //小写
            w += (c - 'A' + 'a');
        }
        else if(! w.empty()){ // string 有这个
            if (myMap.find(w) == myMap.end()) { //查找
                myMap[w] = 1;
            }
            else {
                myMap[w] ++; //赋值查值都可以直接用方括号哒!
            } 
            w.clear(); // string 有这个
        }
    }
    if (!w.empty()) { //最后一个词别忘了!
        if (myMap.find(w) == myMap.end()) {
            myMap[w] = 1;
        }
        else {
            myMap[w] ++;
        }
    }

    str_int_map::iterator iter; //迭代器
    string maxWord;
    int maxTime = 0;
    for (iter = myMap.begin(); iter != myMap.end(); iter++) {
        if (iter->second > maxTime) { // first, second
            maxTime = iter->second;
            maxWord = iter->first;
        }
    }
    
    cout << maxWord << " " << maxTime;

    return 0;
}

1070 Mooncake 简单 排序 ,没过

有一个测试点通不过,答案错误。牛客网上都通过了。

1069 The Black Hole 简单

略。秒过。

1068 Find More Coins 背包,最小解

给一堆硬币,还有要求的总值,求能否组成这个值,能的话求出最小的硬币序列。最小是按照字典顺序从第一个数开始比的,比如 1+3+5 = 9 比 2+3+4 = 9 小。

不会做,差点暴搜。想着能不能把每种总量的硬币选择存成一个数组,但是似乎占内存有点大,而且很蠢。

于是参考了 http://blog.csdn.net/xyt8023y/article/details/47255241,向这位同学表示感谢:-)

下图是一个简单的 case,要用 9 块钱,给了 1 2 3 4 5 7 这几个硬币。原始的 dp 表(同样可以压缩到一维数组用)如下,表中存的值 dp[i][j] 是“仅仅使用前 i 个硬币时,能组成的不大于 j 的最大值。”因此递推公式为dp[i][j] = max(dp[i - 1][j - c[i]] + c[i], dp[i - 1][j],即要么用 c[i] 硬币,要么不用。

到这里还和之前写的 dp 没多大区别,最多就是我存的值意思不一样。又用了一个布尔数组 use[n_coin][max_value]来记录“组成值 j 的时候,最优解是否用了第 i 个硬币”,值为真则在下图中表示为浅灰色底色。

怎么找最小序列呢?硬币的面值从大到小排列,在之后遇到 dp[i][j] 更新的时候就把 use[i][j]为真。如果用不用第 i 个硬币,构成的值都一样,也是要更新的。这样就把所用的硬币的最小值往下拉,选用的总是更小的序列。比如本来用的 5,后面拿到了 2 和 3,就给更新掉。

image.png

当表格填满,就可以通过 dp[m] == m来判断是否能构成 m 块钱了。至于硬币序列,就用刚刚记录的布尔数组往上挖,如蓝色箭头,构成 9 用了 1,减掉 1,剩下的构成 8 ,是用了 3,再减掉剩5, 构成 5 就只是用了 5, 没了。

代码倒是很简短:

# include <cstdio>
# include <cstdlib>

int N, M; //n_coins; money_to_pay
bool use[10010][110]; //形成值j的时候,是否要用硬币i
int dp[110]; //前面硬币所能构成的不大于i的最大值
int c[10010]; //硬币面值,0-N

int compar(const void *a, const void *b) {
    return *(int*)b - *(int*)a; //降序
}

int main() {
    scanf("%d %d", &N, &M);
    for (int i = 0; i < N; i++) {
        scanf("%d", c + i);
    }

    qsort(c, N, sizeof(int), compar); //硬币倒序

    for (int i = 0; i < N; i++) {
        for (int j = M; j >= c[i]; j--) {
            if (dp[j - c[i]] + c[i] >= dp[j]) { //有相等的情况也覆盖
                dp[j] = dp[j - c[i]] + c[i];
                use[i][j] = true;
            }
        }
    }

    if (dp[M] != M) {
        printf("No Solution");
    }
    else {
        bool ans[10010] = { false };
        int i = N - 1, j = M;
        while (j != 0) {
            while (!use[i][j]) i--;
            ans[i] = true;
            j -= c[i];
            i--;
        }

        bool first = true;
        for (i = N - 1; i >= 0; i--) { //c[i]是从大到小的,得倒着数
            if (ans[i]) {
                if (!first) {
                    printf(" ");
                }
                else {
                    first = false;
                }
                printf("%d", c[i]);
            }
        }
    }
    
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容