简单DP (Preparing for Xtreme 12.0) | STL map使用
当水题遇上了map大坑
晚上写一个dp,弄了半天样例一直不过,对着队友的代码一行行看,发现跟自己逻辑完全一样啊。。。
然后就逐行输出比对,发现预处理出了问题,把map插入新值的地方改了下,果然就好了。。。
折腾半晚上,不吐不快。
以前使用STL的map时,一直把它当作一种高级数组,很少使用insert来插入键值对,都是直接用下标索引直接插入新值。而在map中查找key时,我也一般直接采取判断mp[key]是否为0。
而这题这样用也没多大问题,就怪我太作了,把tot默认设置为-1,方便++tot后从0开始计数。。。
但是插入跟第一个相同的key时,由于ID[key]==0,就把ID[key]的值更新了。。。
调试半天都没发现这样的bug啊T_T T_T T_T
直接上AC代码:
#include<iostream> #include<vector> #include<cstring> #include<sstream> #include<algorithm> #include<map> using namespace std; const int INF = 0x3f3f3f3f; int b, tot; map<string, int> ID; struct book{ int id; int cost; }books[110]; int dp[1<<22]; int main() { int cost; while(cin>>cost) { books[b].cost = cost; string line, book; getline(cin, line); stringstream ss(line); while(ss>>book) { // if(!ID.count(book)) ID.insert(make_pair(book, ++tot)); // if(ID.find(book)==ID.end()) ID.insert(make_pair(book, ++tot)); // map里没有键book,则插入 if(!ID[book]) ID[book] = ++tot; books[b].id |= 1<<(ID[book]-1); } b++; } int S = 1<<tot; dp[0] = 0; for(int i=1;i<S;i++) dp[i] = INF; for(int i=0;i<S;i++) { for(int j=0;j<b;j++) { dp[i|books[j].id] = min(dp[i|books[j].id], dp[i]+books[j].cost); } } cout<<dp[S-1]<<endl; return 0; }
最后关于map的使用,还是推荐注释部分的写法。
这篇博客讲了这两种插入的效率问题,我想区别不是太大,直接用ID[book]=++tot也是可以的。
在以后的使用中还是要尽量避免直接使用下标访问,应该如果你要访问的key不存在的话,会默认插入新的值,size也会增加。
map的查找操作使用总结如下
-
在map中,由key查找value时,首先要判断map中是否包含key。
-
如果不检查,直接返回map[key],可能会出现意想不到的行为。如果map包含key,没有问题,如果map不包含key,使用下标有一个危险的副作用,会在map中插入一个key的元素,value会取默认值0。
-
map提供了两种方式,查看是否包含key,m.count(key),m.find(key)。
-
m.count(key):由于map不包含重复的key,因此m.count(key)取值为0,或者1,表示是否包含。
-
m.find(key):返回迭代器,判断是否存在。