我是用DP做的。因为可以看到所有人的代码,所以把第一名的代码下载来看了看,他的也是DP。
后来看到官方的解答,其实用贪心+hash可以达到O(n)的效率。
rem的代码
#include <map> #include <set> #include <cmath> #include <queue> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <cassert> #include <numeric> #include <algorithm> #include <iostream> #include <sstream> #include <ctime> using namespace std; typedef long long int64; typedef vector<int> vi; typedef vector<string> vs; typedef vector<double> vd; #define _CRT_SECURE_NO_WARNINGS #define For(i,a,b) for (int i(a),_b(b); i <= _b; ++i) #define Ford(i,a,b) for (int i(a),_b(b); i >= _b; --i) #define Rep(i,n) for (int i(0),_n(n); i < _n; ++i) #define Repd(i,n) for (int i((n)-1); i >= 0; --i) #define Fill(a,c) memset(&a, c, sizeof(a)) #define MP(x, y) make_pair((x), (y)) #define All(v) (v).begin(), (v).end() template<typename T, typename S> T cast(S s) { stringstream ss; ss << s; T res; ss >> res; return res; } template<typename T> inline T sqr(T a) { return a*a; } template<typename T> inline int Size(const T& c) { return (int)c.size(); } template<typename T> inline void checkMin(T& a, T b) { if (b < a) a = b; } template<typename T> inline void checkMax(T& a, T b) { if (b > a) a = b; } char buf[1024*1024]; int main() { freopen("input.txt", "rt", stdin); freopen("output.txt", "wt", stdout); gets(buf); For(test, 1, atoi(buf)) { int s, q; map<string,int> num; gets(buf); s = atoi(buf); Rep(i, s) { gets(buf); num[buf] = i; } gets(buf); q = atoi(buf); vi dp(s, 0); Rep(i, q) { gets(buf); assert(num.count(buf) > 0); int id = num[buf]; Rep(j, s) if (j != id) checkMin(dp[j], dp[id]+1); dp[id] = 1000000; } printf("Case #%d: %d/n", test, *min_element(All(dp))); } exit(0); }
我自己的代码
#include <map> #include <iostream> #include <sstream>//Defines several classes that support iostreams operations on sequences stored in an allocated array of char object. Such sequences are easily converted to and from C strings. using namespace std; template<typename T> inline void checkMin(T& a, T b) { if (b < a) a = b; } template<typename T> inline void checkMax(T& a, T b) { if (b > a) a = b; } const int max_n=1000; int DP[105]; int N,S,Q; map<string,int> num; char temp[105]; int main() { freopen("D://A-small-practice.in","r",stdin); //freopen("D://A-large-practice.out","w",stdout); scanf("%d",&N); for(int i=1;i<=N;i++) { memset(DP,0,sizeof(DP)); scanf("%d",&S); scanf("/n"); for(int j=0;j<S;j++) { gets(temp); num[temp]=j; } scanf("%d",&Q); scanf("/n"); for(int j=0;j<Q;j++) { gets(temp); int index=num[temp]; for(int k=0;k<S;k++) { if(k!=index) checkMin(DP[k],DP[index]+1); } DP[index]=max_n; } int min_cnt=max_n; for(int j=0;j<S;j++) { if(DP[j]<min_cnt) min_cnt=DP[j]; } printf("Case #%d: %d/n",i,min_cnt); } return 0; }
官方解答摘要
Working in the opposite direction, (*) is all we need to achieve; as long as you can partition the list of queries into such segments, it corresponds to a plan of saving the universe. You don't even care about which engine is used for one segment; any engine not appearing as a query on that segment will do. However, you might sometimes pick the same engine for two consecutive segments, laughing at yourself when you realize it; why don't I just join the two segments into one? Because your task is to use as few segments as possible, it is obvious that you want to make each segment as long as possible.
This leads to the greedy solution: Starting from the first query, add one query at a time to the current segment until the names of all S search engines have been encountered. Then we continue this process in a new segment until all queries are processed.
贪心+hash的代码
#include <hash_set> #include <iostream> using namespace std; #define Rep(i,n) for (int i(0),_n(n); i<_n; ++i) int main() { int T; //freopen("..//s.in","r",stdin); //freopen("..//s.out","w",stdout); scanf("%d", &T); Rep(t, T) { int S; scanf("%d", &S); string q; getline(cin, q);//a unread '/n' in scanf Rep(i, S) { getline(cin, q); } int Q; scanf("%d", &Q); getline(cin, q); stdext::hash_set<string> st; int count = 0; Rep(i, Q) { getline(cin, q); if (st.find(q) == st.end()) { if (st.size() == S-1) { st.clear(); count++; } st.insert(q); } } printf("Case #%d: %d/n", t+1, count); } }