2008-12-22レーティングはどのように算出されているか
SRM411 Div1 Easy: SentenceDecomposition
最初プライオリティキューとか駆使して探索していたが(※2つ目のコード。ちゃんと書かないと全テスト通過できないので、250点にしては難しめでは?と思ったけど)これはDPで書くと超簡単に解ける例。
DP、というか再帰とメモ化で解けるパターンを見つける練習が必要。
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
#define all(c) (c).begin(),(c).end()
#define tr(c,i) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)
#define rep(var,n) for(int var=0;var<(n);var++)
string strsort(const string &str) {
vector<char> buf(all(str));
sort(all(buf));
string sorted(all(buf));
return sorted;
}
class SentenceDecomposition {
private:
int score(string orig, string word) {
if (strsort(orig) != strsort(word)) return -1;
int d = orig.length();
for (int i=d-1; i>=0; i--) if (orig[i] == word[i]) d--;
return d;
}
public:
int len;
string sent;
vector<string> valids;
vector<int> memo;
int sub(int len) {
if (len==0) return 0;
if (memo[len] < INT_MAX) return memo[len];
int min_score = INT_MAX;
tr(valids,it) {
int vl = it->length(); if (vl > len) continue;
int subsc = sub(len-vl); if (subsc == INT_MAX) continue;
int sc = score(*it,sent.substr(len-vl,vl)); if (sc == -1) continue;
sc += subsc; if (sc < min_score) min_score = sc;
}
memo[len] = min(memo[len], min_score);
return min_score;
}
int decompose(string sentence, vector<string> validWords) {
sent = sentence; len = sentence.length();
valids = validWords;
memo.resize(len+1); fill(all(memo),INT_MAX);
int topscore = sub(len);
return (topscore == INT_MAX)? -1 : topscore;
}
};
以下、最初に書いたコード。このコードで(何度か修正した末)システムテストも全て通るようになったが、TopCoderの統計情報を見たらこの問題はDPに分類されているので、書き直して上のコードになった。
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <algorithm>
#include <sstream>
#include <cmath>
using namespace std;
#define sz(a) int((a).size())
#define pb push_back
#define all(c) (c).begin(),(c).end()
#define tr(c,i) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)
#define rep(var,n) for(int var=0;var<(n);var++)
bool greater_by_length(const string& s1, const string& s2 )
{
return s1.length() > s2.length();
}
template <typename T> struct better : binary_function<T,T,bool> {
bool operator()(const T& X, const T& Y) const{
// at, score
if (X.first >= Y.first) return X.second < Y.second;
return false;
}
};
string strsort(const string &str) {
vector<char> buf(all(str));
sort(all(buf));
string sorted(all(buf));
return sorted;
}
class SentenceDecomposition {
private:
bool abc[26];
bool usable(const string &str) {
rep(i,str.length()) if (!abc[str[i]-'a']) return false;
return true;
}
int score(string orig, string word) {
int d = orig.length();
for (int i=d-1; i>=0; i--) if (orig[i] == word[i]) d--;
return d;
}
public:
int decompose(string sentence, vector<string> validWords) {
int l=sentence.length();
rep(i,26) abc[i] = false;
rep(i,l) abc[sentence[i]-'a'] = true;
set<string> s;
tr(validWords,wt) if (usable(*wt)) s.insert(*wt);
vector<string> valids(all(s));
sort(all(valids),greater_by_length);
int n=valids.size();
vector<string> words(n);
rep(i,n) {
words[i] = strsort(valids[i]);
}
priority_queue<pair<int,int>, vector<pair<int,int> >, better<pair<int,int> > > pq;
vector<int> said(l+1,INT_MAX);
rep(i,n) {
int wl = words[i].length();
if (0+wl <= l) {
string ss = sentence.substr(0,wl);
if (strsort(ss) == words[i]) {
int sc = score(valids[i],ss);
if (sc < said[wl]) {
pair<int,int> p = make_pair(wl,sc);
pq.push(p);
said[wl] = sc;
}
}
}
}
int topscore = INT_MAX;
while (!pq.empty()) {
int at = pq.top().first, pt = pq.top().second;
pq.pop();
if (at == l) {
topscore = min(topscore,pt);
continue;
}
rep(i,n) {
int wl = words[i].length();
if (at+wl <= l) {
string ss = sentence.substr(at,wl);
if (strsort(ss) == words[i]) {
int newscore = pt+score(valids[i],ss);
if (newscore < topscore) {
if (newscore < said[at+wl]) {
pair<int,int> p = make_pair(at+wl,newscore);
pq.push(p);
said[at+wl] = newscore;
}
}
}
}
}
}
return (topscore == INT_MAX)? -1 : topscore;
}
};
コメント
トラックバック - https://topcoder-g-hatena-ne-jp.jag-icpc.org/n4_t/20081222