Problem:
Problem E: 英語の勉強
Problem Statement
会津合宿に参加予定の高槻さんは勉強熱心で、最近は英語の勉強をがんばっている。彼女は、携帯を使って次のようなゲームをプレイすることで、少しでも多く英単語を覚えようとしている。彼女が持っている携帯は、指で画面を操作するタッチパネル式である。
携帯の画面には、4 * 4のマス目が描かれており、各マスにはアルファベット大文字が書かれている。このゲームは、制限時間T秒の間に、マス目の中に隠されている英単語をたくさん見つけ、発見できた英単語の種類により点数を競うものである。
1つの単語を見つける手順は、次のようになる。まず、単語の1文字目に対応する開始マスを決めて、そこに指を置く。そして、今指を置いているマス目から、上下左右・斜めの、隣接する8方向のマスのいずれかに向かって、指でなぞっていく。ただし、開始マスから現在のマスまですでに辿ったことがあるマスは、通ることができない。単語の終了マスに達したら、そこで指を離す。その瞬間、開始マスから終了マスまで指でなぞった単語1つの点数が加点される。x文字の単語1つをなぞるためには、x秒の時間がかかる。ある単語をなぞってから、次の単語をなぞるための指の移動時間は無視してよい。
入力では、加点対象となる単語の辞書も入力される。この辞書の各単語には、点数が振られている。辞書の中に書かれている単語を指でなぞると、その単語に対応する点数が加算される。ただし、開始マスから終了マスまで、全く同じ指のなぞり方をした単語は、最初の1回しか点数加算されない。辞書に書かれていない単語を指でなぞっても加点はされない。
辞書とゲームの盤面が与えられるので、制限時間内に得られる最大の点数を出力せよ。
Input
各データセットは、以下の形式で入力される。
N
word1 score1
word2 score2
...
wordN scoreN
line1
line2
line3
line4
T
Nは、辞書に含まれる単語の数を表わす整数である。続いてN行にわたって、辞書が入力される。wordiは1つの単語を表わすアルファベット大文字で構成される文字列、scoreiはwordiの単語を指でなぞったときに得られる点数を表わす整数である。辞書の中に、同じ単語が2回以上現れることはない。
続いて4行にわたって、各マス目の文字が入力される。lineiは、4文字のアルファベット大文字だけで構成される文字列である。lineiの左からj文字目は、i行目の左からj番目の文字に対応する。
一番最後に、制限時間を表わす整数Tが入力される。
Constraints
1 <= N <= 100
1 <= wordiの文字列長 <= 8
1 <= scorei <= 100
1 <= T <= 10000
Output
制限時間内に取得できる最高の点数を1行で出力せよ。
Sample Input 1
6
AIZU 10
LINER 6
LINE 4
ALL 2
AS 1
CIEL 10
ASLA
CILI
IRZN
ELEU
21
Output for the Sample Input 1
40
図1に操作例を示す。例えば、次のようになぞると40点となる。
"CIEL"は、文字列の長さが4であるため4秒かけて10点。
"AIZU"は、違うなぞり方をすれば、2つ発見できるため、8秒かけて20点。
"LINER"を5秒かけて6点。
"LINE"を4秒かけて4点。
合計21秒かけて、40点となる。

Submitted solutions:

code_snippet: #include <iostream>
#include <vector>
#include <array>
#include <list>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <memory>
#include <cmath>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <numeric>
#include <climits>
#include <cfloat>
#include <cassert>
#include <random>
#include <set>

struct Coordinate {
	int x, y;
	std::vector<Coordinate> neighbors() const {
		return std::vector<Coordinate> {
			Coordinate{ x - 1, y },
				Coordinate{ x + 1, y },
				Coordinate{ x, y - 1 },
				Coordinate{ x, y + 1 },
				Coordinate{ x - 1, y - 1 },
				Coordinate{ x - 1, y + 1 },
				Coordinate{ x + 1, y - 1 },
				Coordinate{ x + 1, y + 1 }
		};
	}
};
int count(const std::vector<std::string>& state, const std::string& word, const Coordinate current, int position = 0, int used = 0) {
	if (current.x < 0 || state.size() <= current.x || current.y < 0 || state[current.x].size() <= current.y) return 0;
	if ((used & (1 << (current.x * 4 + current.y))) != 0) return 0;
	if (state[current.x][current.y] != word[position]) return 0;
	if (position + 1 == word.size()) return 1;
	used |= 1 << (current.x * 4 + current.y);
	int result = 0;
	for (const auto next : current.neighbors()) {
		result += count(state, word, next, position + 1, used);
	}
	return result;
}
int main() {
	int n; std::cin >> n;
	std::vector<std::pair<std::string, long long int>> words(n);
	for (auto& pair : words) std::cin >> pair.first >> pair.second;
	std::vector<std::string> state(4); for (auto& line : state) std::cin >> line;
	std::vector<int> pattern(n, 0);
	for (auto i = 0; i < words.size(); ++i) {
		for (auto x = 0; x < 4; ++x) for (auto y = 0; y < 4; ++y) {
			pattern[i] += count(state, words[i].first, Coordinate{ x, y });
		}
	}
	int t; std::cin >> t;
	std::vector<long long int> memo(t + 1, 0);
	for (auto i = 0; i < words.size(); ++i) {
		int pat = pattern[i];
		for (auto j = 0; pat >= (1 << j); ++j) {
			pat -= 1 << j;
			for (auto k = t; k >= (words[i].first.size() << j); --k) {
				memo[k] = std::max(memo[k], memo[k - (words[i].first.size() << j)] + (words[i].second << j));
			}
		}
		if (pat != 0) for (auto k = t; k >= pat * words[i].first.size(); --k) {
			memo[k] = std::max(memo[k], memo[k - pat * words[i].first.size()] + pat * words[i].second);
		}
	}
	std::cout << memo.back() << std::endl;
}
accuracy: 1
time_ms: 30
memory_kb: 3292
final_rank: 4

code_snippet: #include <iostream>
#include <list>
#include <vector>
#include <string>
#include <algorithm>
#include <climits>
#include <set>
#include <map>
#include <utility>
#include <functional>
using namespace std;

using ll = long long int;
using P = pair<int, int>;
string word[100];
int score[100];
string line[4];
set<string> words;
map<string, int> cnt;
bool vis[4][4];
vector<P> v[10];
ll sum[10];
ll sum_v[10][10001];
ll dp[10][10001];
int N, T;
void dfs(int x, int y, int d, string &s) {
	if (words.count(s) > 0) {
		cnt[s]++;
	}
	if (d > 8) return;
	for (int dx = -1; dx <= 1; dx++) {
		for (int dy = -1; dy <= 1; dy++) {
			if(dx==0 && dy==0) continue;
			int nx = x + dx;
			int ny = y + dy;
			if (0 > nx || nx >= 4 || 0 > ny || ny >= 4 || vis[ny][nx]) continue;
			vis[ny][nx] = 1;
			s.push_back(line[ny][nx]);
			dfs(nx, ny, d + 1, s);
			vis[ny][nx] = 0;
			s.pop_back();
		}
	}
}
int main() {
	cin >> N;
	for (int i = 0; i < N; i++) {
		cin >> word[i] >> score[i];
		words.insert(word[i]);
	}
	for (int i = 0; i < 4; i++) cin >> line[i];
	cin >> T;
	string s = "";
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			s.push_back(line[i][j]);
			vis[i][j] = 1;
			dfs(j, i, 1, s);
			vis[i][j] = 0;
			s.pop_back();
		}
	}
	for (int i = 0; i < N; i++) {
		if (cnt.count(word[i])>0) {
			v[word[i].size()].emplace_back(score[i], cnt[word[i]]);
			sum[word[i].size()] += cnt[word[i]];
		}
	}
	for (int i = 1; i <= 8; i++) {
		sort(v[i].begin(), v[i].end(), greater<P>());
	}
	for (int i = 1; i <= 8; i++) {
		int idx = 0, k = 0;
		for (int j = 1; j <= min(sum[i], 10000LL); j++) {
			sum_v[i][j] = sum_v[i][j - 1] + v[i][idx].first;
			k++;
			if (v[i][idx].second <= k) {
				idx++;
				k = 0;
			}
		}
	}
	dp[0][0] = 0;
	for (int i = 1; i <= 8; i++) {
		for (int j = 0; j <= T; j++) {
			for (int k = 0; k <= min((ll)(j / i), min(sum[i], 10000LL)); k++) {
				dp[i][j] = max(dp[i][j], dp[i - 1][j - i*k] + sum_v[i][k]);
			}
		}
	}
	ll ans = 0;
	for (int i = 1; i <= T; i++) {
		ans = max(ans, dp[8][i]);
	}
	cout << ans << endl;
}
accuracy: 1
time_ms: 130
memory_kb: 4132
final_rank: 7

code_snippet: #include <bits/stdc++.h>

#define ALL(a) (a).begin(), (a).end()
#define llong long long

using namespace std;
int dx[] = {-1,0,1,-1,1,-1,0,1};
int dy[] = {1,1,1,0,0,-1,-1,-1};

int knapsack(vector<int> &w, vector<int> &v, int t){
	int n = w.size();
	int cur = 0;
	int nxt = 1;
	vector<vector<int>> dp(2, vector<int>(t+1,-1));
	dp[0][0] = 0;
	for(int i = 0; i < n; i++){
		for(int j = 0; j <= t; j++){
			if(dp[cur][j] == -1) continue;
			dp[nxt][j] = max(dp[nxt][j], dp[cur][j]);
			if(j + w[i] <= t) dp[nxt][j + w[i]] = max(dp[nxt][j + w[i]], dp[cur][j] + v[i]);
		}

		swap(cur, nxt);
	}
	
	int ret = 0;
	for(auto x : dp[cur]) ret = max(ret, x);
	return ret;
}

void dfs_imp(vector<vector<char>> &m, map<string, int> &cnt, int i, int j, vector<vector<bool>> &visited, string &str){
	visited[i][j] = true;
	str.push_back(m[i][j]);
//	cerr << str << endl;
	if(cnt.find(str) != cnt.end()) cnt[str]++;
	if(str.size() >= 8){
		visited[i][j] = false;
		str.pop_back();
		return;
	}
	for(int k = 0; k < 8; k++){
		int nextx = i+dx[k], nexty = j+dy[k];
		if(nextx < 0 || 4 <= nextx || nexty < 0 || 4 <= nexty)continue;
		if(!visited[nextx][nexty]){
			dfs_imp(m, cnt, i+dx[k], j+dy[k], visited, str);

		}
	}
	visited[i][j] = false;
	str.pop_back();
}

void dfs(vector<vector<char>> &m, map<string, int> &cnt, int i, int j){
	vector<vector<bool>> visited(4, vector<bool>(4,false));
	visited[i][j] = true;
	string str;
	str.push_back(m[i][j]);
	if(cnt.find(str) != cnt.end()) cnt[str]++;
	for(int k = 0; k < 8; k++){
		int nextx = i+dx[k], nexty = j+dy[k];
		if(nextx < 0 || 4 <= nextx || nexty < 0 || 4 <= nexty)continue;
		dfs_imp(m, cnt, nextx, nexty, visited, str);
	}
	visited[i][j] = false;
}

signed main(){
	
	cin.tie(0);
    ios::sync_with_stdio(false);
	int n; cin >> n;
	map<string, int> words;
	for(int i = 0; i < n; i++){
		string w; cin >> w;
		int s; cin >> s;
		words[w] = s;
	}
	vector<vector<char>> m(4, vector<char>(4));
	for(auto &a : m)for(auto &e : a)cin >> e;
	int t; cin >> t;

	map<string, int> cnt;
	for(auto e : words)cnt[e.first] = 0;
	for(int i = 0; i < 4; i++)for(int j = 0; j < 4; j++){
		dfs(m, cnt, i, j);
	}
//	for(auto e : cnt)cerr << e.first << ":" << e.second << endl;

	vector<int> v,w;
	for(auto e : words){
		if(cnt[e.first] == 0)continue;
        int sum = 0;
		for(int i = 1;; i *= 2){
			if(sum + i < cnt[e.first]){
                w.push_back(i * e.first.size());
			    v.push_back(i * e.second);
            }else{
                i = cnt[e.first] - sum;
                w.push_back(i * e.first.size());
                v.push_back(i * e.second);
                break;
            }
		    sum += i;
        }
	}
	cout << knapsack(w,v, t) << endl;

	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3340
final_rank: 6

code_snippet: #include <bits/stdc++.h>

#define ALL(a) (a).begin(), (a).end()
#define llong long long

using namespace std;
int dx[] = {-1,0,1,-1,1,-1,0,1};
int dy[] = {1,1,1,0,0,-1,-1,-1};

int knapsack(vector<int> &w, vector<int> &v, int t){
	int n = w.size();
	int cur = 0;
	int nxt = 1;
	vector<vector<int>> dp(2, vector<int>(t+1,-1));
	dp[0][0] = 0;
	for(int i = 0; i < n; i++){
		for(int j = 0; j <= t; j++){
			if(dp[cur][j] == -1) continue;
			dp[nxt][j] = max(dp[nxt][j], dp[cur][j]);
			if(j + w[i] <= t) dp[nxt][j + w[i]] = max(dp[nxt][j + w[i]], dp[cur][j] + v[i]);
		}

		swap(cur, nxt);
	}
	
	int ret = 0;
	for(auto x : dp[cur]) ret = max(ret, x);
	return ret;
}

void dfs_imp(vector<vector<char>> &m, map<string, int> &cnt, int i, int j, vector<vector<bool>> &visited, string &str){
	visited[i][j] = true;
	str.push_back(m[i][j]);
//	cerr << str << endl;
	if(cnt.find(str) != cnt.end()) cnt[str]++;
	if(str.size() >= 8){
		visited[i][j] = false;
		str.pop_back();
		return;
	}
	for(int k = 0; k < 8; k++){
		int nextx = i+dx[k], nexty = j+dy[k];
		if(nextx < 0 || 4 <= nextx || nexty < 0 || 4 <= nexty)continue;
		if(!visited[nextx][nexty]){
			dfs_imp(m, cnt, i+dx[k], j+dy[k], visited, str);

		}
	}
	visited[i][j] = false;
	str.pop_back();
}

void dfs(vector<vector<char>> &m, map<string, int> &cnt, int i, int j){
	vector<vector<bool>> visited(4, vector<bool>(4,false));
	visited[i][j] = true;
	string str;
	str.push_back(m[i][j]);
	if(cnt.find(str) != cnt.end()) cnt[str]++;
	for(int k = 0; k < 8; k++){
		int nextx = i+dx[k], nexty = j+dy[k];
		if(nextx < 0 || 4 <= nextx || nexty < 0 || 4 <= nexty)continue;
		dfs_imp(m, cnt, nextx, nexty, visited, str);
	}
	visited[i][j] = false;
}

signed main(){
	
	cin.tie(0);
    ios::sync_with_stdio(false);
	int n; cin >> n;
	map<string, int> words;
	for(int i = 0; i < n; i++){
		string w; cin >> w;
		int s; cin >> s;
		words[w] = s;
	}
	vector<vector<char>> m(4, vector<char>(4));
	for(auto &a : m)for(auto &e : a)cin >> e;
	int t; cin >> t;

	map<string, int> cnt;
	for(auto e : words)cnt[e.first] = 0;
	for(int i = 0; i < 4; i++)for(int j = 0; j < 4; j++){
		dfs(m, cnt, i, j);
	}
//	for(auto e : cnt)cerr << e.first << ":" << e.second << endl;

	vector<int> v,w;
	for(auto e : words){
		if(cnt[e.first] == 0)continue;
		for(int i = 1;; i *= 2){
		    if(i < cnt[e.first]){
			    w.push_back(i * e.first.size());
			    v.push_back(i * e.second);
		    }else{
		        i /= 2;
		        i = cnt[e.first] - i;
		        w.push_back(i * e.first.size());
		        v.push_back(i * e.second);
		        break;
		    }
		}
	}
	cout << knapsack(w,v, t) << endl;

	return 0;
}
accuracy: 0.03225806451612903
time_ms: 10
memory_kb: 3256
final_rank: 20

code_snippet: #include <vector>
#include <algorithm>
#include <string>
#include <iostream>
#include <cstdio>
#include <map>
#include <queue>
#include <utility>
#include <tuple>
using namespace std;

const int H = 4, W = 4;
char board[H][W];

int dp[110][10010];
const int dx[] = {1, -1, 0, 0, 1, -1, 1, -1};
const int dy[] = {0, 0, 1, -1, 1, 1, -1, -1};

int main() {
  int N; cin >> N;
  map<string, int> point_map, cnt_map;
  for(int i=0; i<N; i++) {
    string pat; int point;
    cin >> pat >> point;
    point_map[pat] = point;
    cnt_map[pat] = 0;
  }

  for(int i=0; i<H; i++) {
    for(int j=0; j<W; j++) {
      cin >> board[i][j];
    }
  }

  fill(dp[0], dp[N+1], -1);
  dp[0][0] = 0;

  // pos, bit, string
  queue< tuple<int, int, string> > que;
  for(int i=0; i<H; i++) {
    for(int j=0; j<W; j++) {
      int idx = i * W + j;
      int bit = (1 << idx);
      que.push(make_tuple(idx, bit, string(1, board[i][j])));
    }
  }

  while(que.size()) {
    auto tup = que.front(); que.pop();
    int pos, bit; string str; tie(pos, bit, str) = tup;

    if(cnt_map.count(str)) {
      cnt_map[str]++;
    }

    if(str.size() == 8) continue;
    int x = pos / W, y = pos % W;
    for(int k=0; k<8; k++) {
      int nx = x + dx[k], ny = y + dy[k];
      if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
      int idx = nx * W + ny;
      if(bit >> idx & 1) continue;
      int nbit = bit | (1 << idx);
      string nstr = str + board[nx][ny];
      que.push(make_tuple(idx, nbit, nstr));
    }
  }

  int time_limit; cin >> time_limit;

  /*
  for(auto e : cnt_map) {
    cerr << e.first << ", " << e.second << endl;
  }
  */

  int i = 0;
  for(auto e : cnt_map) {
    int cost = e.first.size(), score = point_map[e.first];
    int num = e.second;

    for(int j=0; j<=time_limit; j++) {
      dp[i+1][j] = max(dp[i+1][j], dp[i][j]);
    }
    
    for(int k=0; num; k++) {
      int take = min(num, 1 << k);
      int take_time = cost * take;
      int take_point = score * take;
      // fprintf(stderr, "i = %d, k = %d, take = %d\n", i, k, take);
      for(int j=time_limit - take_time; j>=0; j--) {
        if(dp[i][j] >= 0) {
          dp[i+1][j + take_time] = max(dp[i+1][j + take_time], dp[i][j] + take_point);
        }
        if(dp[i+1][j] >= 0) {
          dp[i+1][j + take_time] = max(dp[i+1][j + take_time], dp[i+1][j] + take_point);
        }
      }
      num -= take;
    }
    for(int j=0; j<=time_limit; j++) {
      if(dp[i+1][j] < 0) continue;
      // fprintf(stderr, "dp[%d][%d] = %d\n", i+1, j, dp[i+1][j]);
    }
    i++;
  }
    
  int ans = 0;
  for(int i=0; i<=time_limit; i++) {
    ans = max(ans, dp[N][i]);
  }
  cout << ans << endl;
  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 18524
final_rank: 15

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<complex>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
using namespace std;
typedef long long ll;
typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 1000000007;
typedef long double ld;
typedef complex<ld> Point;
const ll INF = mod * mod;
typedef pair<int, int> P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
const ld eps = 1e-6;
const ld pi = acos(-1.0);
typedef pair<ld, ld> LDP;
typedef pair<ll, ll> LP;

int dx[8] = { 1,1,1,0,-1,-1,-1,0 };
int dy[8] = { 1,0,-1,-1,-1,0,1,1 };

char mp[4][4];
bool used[4][4];

vector<string> v;
string cur;


void dfs(int x,int y) {
	v.push_back(cur);
	if (cur.length() == 8)return;
	rep(k, 8) {
		int nx = x + dx[k], ny = y + dy[k];
		if (nx < 0 || ny < 0 || nx >= 4 || ny >= 4)continue;
		if (used[nx][ny])continue;
		cur.push_back(mp[nx][ny]);
		used[nx][ny] = true;
		dfs(nx, ny);
		used[nx][ny] = false;
		cur.pop_back();
	}
}

int dp[10001];

void solve() {
	sort(v.begin(), v.end());
	int n; cin >> n;
	vector<string> s(n); vector<int> c(n);
	rep(i, n) {
		cin >> s[i] >> c[i];
	}
	rep(i, 4) {
		rep(j, 4)cin >> mp[i][j];
	}
	rep(i, 4) {
		rep(j, 4) {
			cur.push_back(mp[i][j]);
			used[i][j] = true;
			dfs(i, j);
			used[i][j] = false;
			cur.pop_back();
		}
	}
	sort(v.begin(), v.end());
	int t; cin >> t;
	rep(i, n) {
		int num = upper_bound(v.begin(), v.end(), s[i]) - lower_bound(v.begin(), v.end(), s[i]);
		int len = s[i].length();
		per(k, t + 1) {
			
			rep1(j, num) {
				int ni = k + j * len;
				if (ni > t)break;
				dp[ni] = max(dp[ni], dp[k] + j * c[i]);
			}
		}
	}
	int ans = 0;
	rep(i, t + 1)ans = max(ans, dp[i]);
	cout << ans << endl;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	solve();
	//stop
	return 0;
}
accuracy: 1
time_ms: 870
memory_kb: 19256
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

int n;
map<string,int> s, ct;

string f[4];

bool vis[4][4]={};
void dfs(int d, int y, int x, string now){
    if(s.count(now)) ++ct[now];
    if(d==8) return;

    for(int dy=-1; dy<=1; ++dy)for(int dx=-1; dx<=1; ++dx){
        int ny = y+dy , nx = x+dx;
        if(0<=ny && ny<4 && 0<=nx && nx<4 && !vis[ny][nx]){
            vis[ny][nx] = true;
            dfs(d+1,ny,nx,now+f[ny][nx]);
            vis[ny][nx] = false;
        }
    }
}

const int N = 10001;

vector<int> v[9];
int dp[N]={};

int main(){
    cin >>n;
    rep(i,n){
        string w;
        int score;
        cin >>w >>score;
        s[w] = score;
    }

    rep(i,4) cin >>f[i];

    rep(i,4)rep(j,4){
        vis[i][j] = true;
        dfs(1,i,j,string(1,f[i][j]));
        vis[i][j] = false;
    }

    for(const auto &p:ct){
        int sz = p.fi.size();
        rep(i,p.se) v[sz].pb(s[p.fi]);
    }

    int T;
    cin >>T;

    for(int i=1; i<=8; ++i){
        vector<int> x = v[i];
        sort(all(x),greater<int>());

        int X = x.size();
        if(X>10000/i) x.resize(10000/i);
        X = x.size();

        rep(j,X){
            for(int k=T-i; k>=0; --k){
                dp[k+i] = max(dp[k+i], dp[k]+x[j]);
            }
        }
    }

    int ans = 0;
    rep(i,T+1) ans = max(ans,dp[i]);
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 5256
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

int n;
map<string,int> s, ct;

string f[4];

bool vis[4][4]={};
void dfs(int d, int y, int x, string now){
    if(s.count(now)) ++ct[now];
    if(d==8) return;

    for(int dy=-1; dy<=1; ++dy)for(int dx=-1; dx<=1; ++dx){
        int ny = y+dy , nx = x+dx;
        if(0<=ny && ny<4 && 0<=nx && nx<4 && !vis[ny][nx]){
            vis[ny][nx] = true;
            dfs(d+1,ny,nx,now+f[ny][nx]);
            vis[ny][nx] = false;
        }
    }
}

const int N = 10001;

vector<int> v[9];
int dp[N]={};

int main(){
    cin >>n;
    rep(i,n){
        string w;
        int score;
        cin >>w >>score;
        s[w] = score;
    }

    rep(i,4) cin >>f[i];

    rep(i,4)rep(j,4){
        vis[i][j] = true;
        dfs(1,i,j,string(1,f[i][j]));
        vis[i][j] = false;
    }

    for(const auto &p:ct){
        int sz = p.fi.size();
        rep(i,p.se) v[sz].pb(s[p.fi]);
    }

    int T;
    cin >>T;

    for(int i=1; i<=8; ++i){
        vector<int> x = v[i];
        sort(all(x));

        int X = x.size();
        if(X>10000/i) x.resize(10000/i);
        X = x.size();

        rep(j,X){
            for(int k=T-i; k>=0; --k){
                dp[k+i] = max(dp[k+i], dp[k]+x[j]);
            }
        }
    }

    int ans = 0;
    rep(i,T+1) ans = max(ans,dp[i]);
    cout << ans << endl;
    return 0;
}
accuracy: 0.25806451612903225
time_ms: 70
memory_kb: 3740
final_rank: 19

code_snippet: #include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


struct Node{
	int children[26],finish_id;
};

struct Data{
	void set(int arg_row,int arg_col,int arg_parent,int arg_node_id){
		row = arg_row;
		col = arg_col;
		parent = arg_parent;
		node_id = arg_node_id;
	}
	int row,col,parent,node_id;
	bool check[4][4];
};

int score[101],num[101],len[101];
int N,index_table[26];
int diff_row[8] = {-1,-1,-1,0,0,1,1,1},diff_col[8] = {-1,0,1,-1,1,-1,0,1};
Node nodes[26][800];

char base_map[4][5];


bool rangeCheck(int row,int col){
	if(row >= 0 && row <= 3 && col >= 0 && col <= 3)return true;
	else{
		return false;
	}
}

void recursive(Data data){

	int adj_row,adj_col,next_node;
	for(int i = 0; i < 8; i++){
		adj_row = data.row+diff_row[i];
		adj_col = data.col+diff_col[i];

		if(rangeCheck(adj_row,adj_col) == false || data.check[adj_row][adj_col] == true)continue;

		next_node = base_map[adj_row][adj_col]-'A';
		if(nodes[data.parent][data.node_id].children[next_node] == -1)continue;

		Data new_data;
		new_data.set(adj_row,adj_col,data.parent,nodes[data.parent][data.node_id].children[next_node]);
		if(nodes[new_data.parent][new_data.node_id].finish_id != -1){
			num[nodes[new_data.parent][new_data.node_id].finish_id]++;
		}
		for(int a = 0; a < 4; a++){
			for(int b = 0; b < 4; b++)new_data.check[a][b] = data.check[a][b];
		}
		new_data.check[adj_row][adj_col] = true;
		recursive(new_data);
	}
}


int main(){

	int N;
	scanf("%d",&N);

	for(int i = 1; i <= N; i++)num[i] = 0;

	for(int i = 0; i < 26; i++)index_table[i] = 1;
	for(int i = 0; i < 26; i++){
		for(int k = 0; k < 800; k++){
			nodes[i][k].finish_id = -1;
			for(int p = 0; p < 26; p++){
				nodes[i][k].children[p] = -1;
			}
		}
	}

	char  buf[9];
	int parent,tmp_index,node_id,length;
	bool FLG;

	for(int i = 1; i <= N; i++){
		scanf("%s %d",buf,&score[i]);
		for(length = 0; buf[length] != '\0';length++);
		len[i]	= length;
		parent = buf[0]-'A';
		tmp_index = 1;
		node_id = 0;
		while(buf[tmp_index] != '\0'){
			if(nodes[parent][node_id].children[buf[tmp_index]-'A'] == -1){
				nodes[parent][node_id].children[buf[tmp_index]-'A'] = index_table[parent]++;
				node_id = nodes[parent][node_id].children[buf[tmp_index]-'A'];
			}else{
				node_id = nodes[parent][node_id].children[buf[tmp_index]-'A'];
			}
			tmp_index++;
		}
		nodes[parent][node_id].finish_id = i;
	}

	for(int row = 0; row < 4; row++)scanf("%s",base_map[row]);
	int T;
	scanf("%d",&T);

	for(int row = 0; row < 4; row++){
		for(int col = 0; col < 4; col++){
			Data new_data;
			new_data.set(row,col,base_map[row][col]-'A',0);
			if(nodes[base_map[row][col]-'A'][0].finish_id != -1){
				num[nodes[base_map[row][col]-'A'][0].finish_id]++;
			}
			for(int a = 0; a < 4; a++){
				for(int b = 0; b < 4; b++)new_data.check[a][b] = false;
			}
			new_data.check[row][col] = true;
			recursive(new_data);
		}
	}


	int dp[T+1],next_dp[T+1];
	dp[0] = 0;
	next_dp[0] = 0;
	for(int i = 1; i <= T; i++){
		dp[i] = -1;
		next_dp[i] = -1;
	}

	for(int word = 1; word <= N; word++){
		if(num[word] == 0)continue;

		for(int i = 1; i <= num[word]; i++){
			for(int k = T; k-i*len[word] >= 0; k--){
				if(dp[k-i*len[word]] >= 0){
					next_dp[k] = max(next_dp[k],dp[k-i*len[word]]+i*score[word]);
				}
			}
		}
		for(int i = 0; i <= T; i++)dp[i] = next_dp[i];
	}

	int maximum = -1;
	for(int i = 0; i <= T; i++)maximum = max(maximum,dp[i]);

	printf("%d\n",maximum);

	return 0;
}
accuracy: 1
time_ms: 730
memory_kb: 5476
final_rank: 13

code_snippet: #include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


struct Node{
	int children[26],finish_id;
};

struct Data{
	void set(int arg_row,int arg_col,int arg_parent,int arg_node_id){
		row = arg_row;
		col = arg_col;
		parent = arg_parent;
		node_id = arg_node_id;
	}
	int row,col,parent,node_id;
	bool check[4][4];
};

int score[101],num[101],len[101];
int N,index_table[26];
int diff_row[8] = {-1,-1,-1,0,0,1,1,1},diff_col[8] = {-1,0,1,-1,1,-1,0,1};
Node nodes[26][800]; //???????????¨

char base_map[4][5];


bool rangeCheck(int row,int col){
	if(row >= 0 && row <= 3 && col >= 0 && col <= 3)return true;
	else{
		return false;
	}
}

void recursive(Data data){

	int adj_row,adj_col,next_node;
	for(int i = 0; i < 8; i++){
		adj_row = data.row+diff_row[i];
		adj_col = data.col+diff_col[i];

		if(rangeCheck(adj_row,adj_col) == false || data.check[adj_row][adj_col] == true)continue;

		next_node = base_map[adj_row][adj_col]-'A';
		if(nodes[data.parent][data.node_id].children[next_node] == -1)continue;

		Data new_data;
		new_data.set(adj_row,adj_col,data.parent,nodes[data.parent][data.node_id].children[next_node]);
		if(nodes[new_data.parent][new_data.node_id].finish_id != -1){
			num[nodes[new_data.parent][new_data.node_id].finish_id]++;
		}
		for(int a = 0; a < 4; a++){
			for(int b = 0; b < 4; b++)new_data.check[a][b] = data.check[a][b];
		}
		new_data.check[adj_row][adj_col] = true;
		recursive(new_data);
	}
}


int main(){

	int N;
	scanf("%d",&N);

	for(int i = 1; i <= N; i++)num[i] = 0;

	for(int i = 0; i < 26; i++)index_table[i] = 1;
	for(int i = 0; i < 26; i++){
		for(int k = 0; k < 800; k++){
			nodes[i][k].finish_id = -1;
			for(int p = 0; p < 26; p++){
				nodes[i][k].children[p] = -1;
			}
		}
	}

	char  buf[9];
	int parent,tmp_index,node_id,length;

	for(int i = 1; i <= N; i++){
		scanf("%s %d",buf,&score[i]);
		for(length = 0; buf[length] != '\0';length++);
		len[i]	= length;
		parent = buf[0]-'A';
		tmp_index = 1;
		node_id = 0;
		while(buf[tmp_index] != '\0'){
			if(nodes[parent][node_id].children[buf[tmp_index]-'A'] == -1){
				nodes[parent][node_id].children[buf[tmp_index]-'A'] = index_table[parent]++;
				node_id = nodes[parent][node_id].children[buf[tmp_index]-'A'];
			}else{
				node_id = nodes[parent][node_id].children[buf[tmp_index]-'A'];
			}
			tmp_index++;
		}
		nodes[parent][node_id].finish_id = i;
	}

	for(int i = 0; i < 26; i++){
		if(nodes[i][0].finish_id != -1){
			num[nodes[i][0].finish_id]++;
		}
	}

	for(int row = 0; row < 4; row++)scanf("%s",base_map[row]);
	int T;
	scanf("%d",&T);

	for(int row = 0; row < 4; row++){
		for(int col = 0; col < 4; col++){
			Data new_data;
			new_data.set(row,col,base_map[row][col]-'A',0);
			for(int a = 0; a < 4; a++){
				for(int b = 0; b < 4; b++)new_data.check[a][b] = false;
			}
			new_data.check[row][col] = true;
			recursive(new_data);
		}
	}


	int dp[T+1],next_dp[T+1];
	dp[0] = 0;
	next_dp[0] = 0;
	for(int i = 1; i <= T; i++){
		dp[i] = -1;
		next_dp[i] = -1;
	}

	for(int word = 1; word <= N; word++){
		if(num[word] == 0)continue;

		for(int i = 1; i <= num[word]; i++){
			for(int k = T; k-i*len[word] >= 0; k--){
				if(dp[k-i*len[word]] >= 0){
					next_dp[k] = max(next_dp[k],dp[k-i*len[word]]+i*score[word]);
				}
			}
		}
		for(int i = 0; i <= T; i++)dp[i] = next_dp[i];
	}

	int maximum = -1;
	for(int i = 0; i <= T; i++)maximum = max(maximum,dp[i]);

	printf("%d\n",maximum);

	return 0;
}
accuracy: 0.4838709677419355
time_ms: 170
memory_kb: 5484
final_rank: 17

code_snippet: #include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


struct Node{
	int children[26],finish_id;
};

struct Data{
	void set(int arg_row,int arg_col,int arg_parent,int arg_node_id){
		row = arg_row;
		col = arg_col;
		parent = arg_parent;
		node_id = arg_node_id;
	}
	int row,col,parent,node_id;
	bool check[4][4];
};

int score[101],num[101],len[101];
int N,index_table[26];
int diff_row[8] = {-1,-1,-1,0,0,1,1,1},diff_col[8] = {-1,0,1,-1,1,-1,0,1};
bool is_palindrome[101];
Node nodes[26][800];

char base_map[4][5];


bool rangeCheck(int row,int col){
	if(row >= 0 && row <= 3 && col >= 0 && col <= 3)return true;
	else{
		return false;
	}
}

void recursive(Data data){

	int adj_row,adj_col,next_node;
	for(int i = 0; i < 8; i++){
		adj_row = data.row+diff_row[i];
		adj_col = data.col+diff_col[i];

		if(rangeCheck(adj_row,adj_col) == false || data.check[adj_row][adj_col] == true)continue;

		next_node = base_map[adj_row][adj_col]-'A';
		if(nodes[data.parent][data.node_id].children[next_node] == -1)continue;

		Data new_data;
		new_data.set(adj_row,adj_col,data.parent,nodes[data.parent][data.node_id].children[next_node]);
		if(nodes[new_data.parent][new_data.node_id].finish_id != -1){
			num[nodes[new_data.parent][new_data.node_id].finish_id]++;
		}
		for(int a = 0; a < 4; a++){
			for(int b = 0; b < 4; b++)new_data.check[a][b] = data.check[a][b];
		}
		new_data.check[adj_row][adj_col] = true;
		recursive(new_data);
	}
}


int main(){

	int N;
	scanf("%d",&N);

	for(int i = 1; i <= N; i++)num[i] = 0;

	for(int i = 0; i < 26; i++)index_table[i] = 1;
	for(int i = 0; i < 26; i++){
		for(int k = 0; k < 800; k++){
			nodes[i][k].finish_id = -1;
			for(int p = 0; p < 26; p++){
				nodes[i][k].children[p] = -1;
			}
		}
	}

	char  buf[9];
	int parent,tmp_index,node_id,length;
	bool FLG;

	for(int i = 1; i <= N; i++){
		scanf("%s %d",buf,&score[i]);
		for(length = 0; buf[length] != '\0';length++);
		len[i]	= length;
		FLG = true;
		for(int k = 0; k < length/2; k++){
			if(buf[k] != buf[length-1-k]){
				FLG = false;
				break;
			}
		}
		is_palindrome[i] = FLG;
		parent = buf[0]-'A';
		tmp_index = 1;
		node_id = 0;
		while(buf[tmp_index] != '\0'){
			if(nodes[parent][node_id].children[buf[tmp_index]-'A'] == -1){
				nodes[parent][node_id].children[buf[tmp_index]-'A'] = index_table[parent]++;
				node_id = nodes[parent][node_id].children[buf[tmp_index]-'A'];
			}else{
				node_id = nodes[parent][node_id].children[buf[tmp_index]-'A'];
			}
			tmp_index++;
		}
		nodes[parent][node_id].finish_id = i;
	}

	for(int i = 0; i < 26; i++){
		if(nodes[i][0].finish_id != -1){
			num[nodes[i][0].finish_id]++;
		}
	}

	for(int row = 0; row < 4; row++)scanf("%s",base_map[row]);
	int T;
	scanf("%d",&T);

	for(int row = 0; row < 4; row++){
		for(int col = 0; col < 4; col++){
			Data new_data;
			new_data.set(row,col,base_map[row][col]-'A',0);
			for(int a = 0; a < 4; a++){
				for(int b = 0; b < 4; b++)new_data.check[a][b] = false;
			}
			new_data.check[row][col] = true;
			recursive(new_data);
		}
	}


	int dp[T+1],next_dp[T+1];
	dp[0] = 0;
	next_dp[0] = 0;
	for(int i = 1; i <= T; i++){
		dp[i] = -1;
		next_dp[i] = -1;
	}

	for(int i = 1; i <= N; i++){
		if(is_palindrome[i])num[i] /= 2;
	}

	for(int word = 1; word <= N; word++){
		if(num[word] == 0)continue;

		for(int i = 1; i <= num[word]; i++){
			for(int k = T; k-i*len[word] >= 0; k--){
				if(dp[k-i*len[word]] >= 0){
					next_dp[k] = max(next_dp[k],dp[k-i*len[word]]+i*score[word]);
				}
			}
		}
		for(int i = 0; i <= T; i++)dp[i] = next_dp[i];
	}

	int maximum = -1;
	for(int i = 0; i <= T; i++)maximum = max(maximum,dp[i]);

	printf("%d\n",maximum);

	return 0;
}
accuracy: 0.41935483870967744
time_ms: 180
memory_kb: 5460
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define GET_MACRO(_1, _2, _3, NAME, ...) NAME
#define _repl(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define _rep(i,n) _repl(i,0,n)
#define rep(...) GET_MACRO(__VA_ARGS__, _repl, _rep)(__VA_ARGS__)
#define mp(a,b) make_pair((a),(b))
#define pb(a) push_back((a))
#define all(x) (x).begin(),(x).end()
#define uniq(x) sort(all(x)),(x).erase(unique(all(x)),end(x))
#define fi first
#define se second
#define dbg(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
void _dbg(string){cout<<endl;}
template<class H,class... T> void _dbg(string s,H h,T... t){int l=s.find(',');cout<<s.substr(0,l)<<" = "<<h<<", ";_dbg(s.substr(l+1),t...);}
template<class T,class U> ostream& operator<<(ostream &o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream &o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

#define INF 1120000000
#define long long long // for codeforces

int node[1000][26];
int type[1000][26];
int nodes = 0;

string word[100];
int score[100];

char m[6][6];
bool visited[6][6];

inline int init_node(){
  rep(i,26) node[nodes][i] = -1;
  rep(i,26) type[nodes][i] = -1;
  return nodes++;
}

void build_trie(int idx, int l, int node_id){
  if(word[idx].size() == l+1){
    type[node_id][word[idx].back()-'A'] = idx;
    return;
  }
  int c = word[idx][l] - 'A';
  // dbg(idx,l,node_id,word[idx]);
  assert(0<=c && c<26);
  if(node[node_id][c] == -1) node[node_id][c] = init_node();
  build_trie(idx, l+1, node[node_id][c]);
}

int cnt[111];

void dfs(int x, int y, int node_id, int dep){
  int c = m[x][y] - 'A';
  if(type[node_id][c]>=0) cnt[type[node_id][c]]++;

  visited[x][y] = true;
  int nid = node[node_id][c];
  if(nid>=0){
    rep(dx,-1,2) rep(dy,-1,2){
      int nx = x + dx, ny = y + dy;
      if(visited[nx][ny] || m[nx][ny]=='\0') continue;
      if(nid>=0) dfs(nx, ny, nid, dep+1);
    }
  }
  visited[x][y] = false;
}

int main(){
  int n;
  cin>>n;
  rep(i,n) cin>>word[i]>>score[i];

  init_node();
  rep(i,n) build_trie(i,0,0);

  fill(m[0], m[6], '\0');
  fill(visited[0], visited[6], false);
  rep(i,4) scanf("%s", &m[i+1][1]);

  fill(cnt, cnt+n, 0);
  rep(i,1,5)rep(j,1,5) dfs(i,j,0,1);

  int t;
  cin>>t;
  vector<int> dp(t+1, 0);
  rep(i,n){
    vector<int> nxt(dp);
    int sz = word[i].size();
    for(int j=1; sz*j<=t && j<=cnt[i]; j++){
      int c = sz*j;
      int v = score[i]*j;
      for(int k = t-c; k>=0; k--){
        nxt[k+c] = max(nxt[k+c], dp[k]+v);
      }
    }
    swap(dp, nxt);
  }

  cout << *max_element(all(dp)) << endl;

  return 0;
}
accuracy: 1
time_ms: 440
memory_kb: 3380
final_rank: 10

code_snippet: #include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
struct State { int x[4][4]; };
char F[4][4]; vector<pair<int, int>>v; string U[100]; int V[100], dp[10009];
int solve(string S, int depth, int cx, int cy, State Y) {
	if (depth == S.size())return 1;
	int dx[8] = { 1,1,1,0,-1,-1,-1,0 }, dy[8] = { -1,0,1,1,1,0,-1,-1 };
	int cnt = 0;
	for (int i = 0; i < 8; i++) {
		int ex = cx + dx[i], ey = cy + dy[i];
		if (ex < 0 || ey < 0 || ex >= 4 || ey >= 4)continue;
		if (Y.x[ex][ey] == 0 && F[ex][ey] == S[depth]) {
			State Z = Y; Z.x[ex][ey] = 1;
			cnt += solve(S, depth + 1, ex, ey, Z);
		}
	}
	return cnt;
}
int main() {
	int n; cin >> n;
	for (int i = 0; i < n; i++) { cin >> U[i] >> V[i]; }
	for (int i = 0; i < 16; i++)cin >> F[i / 4][i % 4];
	for (int i = 0; i < n; i++) { 
		int c = 0;
		for (int j = 0; j < 16; j++) {
			if (F[j / 4][j % 4] != U[i][0])continue;
			State R; for (int k = 0; k < 16; k++)R.x[k / 4][k % 4] = 0; R.x[j / 4][j % 4] = 1;
			c += solve(U[i], 1, j / 4, j % 4, R);
		}
		for (int j = 0; j < 20; j++) {
			if (c >= (1 << j)) { v.push_back(make_pair(V[i] * (1 << j), U[i].size()*(1 << j))); c -= (1 << j); }
			else { v.push_back(make_pair(V[i] * c, U[i].size()*c)); break; }
		}
	}
	int T; cin >> T; int maxn = 0;
	for (int i = 0; i < v.size(); i++) {
		for (int j = T; j >= v[i].second; j--) {
			dp[j] = max(dp[j], dp[j - v[i].second] + v[i].first); maxn = max(maxn, dp[j]);
		}
	}
	cout << maxn << endl;
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3220
final_rank: 5

code_snippet: #include <bits/stdc++.h>

using namespace std;

namespace {

    typedef double real;
    typedef long long ll;

    template<class K, class V> ostream& operator<<(ostream& os, const pair<K, V>& p) {
        return os << "(" << p.first << "," << p.second << ")";
    }
    template<class T> ostream& operator<<(ostream& os, const vector<T>& vs) {
        if (vs.empty()) return os << "[]";
        os << "[" << vs[0];
        for (int i = 1; i < vs.size(); i++) os << " " << vs[i];
        return os << "]";
    }
    template<class T> istream& operator>>(istream& is, vector<T>& vs) {
        for (auto it = vs.begin(); it != vs.end(); it++) is >> *it;
        return is;
    }

    int N;
    vector<string> ws;
    vector<int> ss;
    int T;
    vector<string> F;
    void input() {
        cin >> N;
        ws.clear(); ws.resize(N);
        ss.clear(); ss.resize(N);
        for (int i = 0; i < N; i++) cin >> ws[i] >> ss[i];
        F.clear(); F.resize(4);
        cin >> F;
        cin >> T;
    }

    vector<int> count;

    void dfs(int i, int j, int y, int x, int used) {
        if (j == ws[i].size()) {
            count[i]++;
            return;
        }
        for (int dy = -1; dy <= 1; dy++) {
            for (int dx = -1; dx <= 1; dx++) {
                if (dy == 0 && dx == 0) continue;
                int ny = y + dy;
                int nx = x + dx;
                if (ny < 0 || ny >= 4 || nx < 0 || nx >= 4) continue;
                if (F[ny][nx] != ws[i][j]) continue;
                if (used & (1 << (4*ny+nx))) continue;
                dfs(i, j + 1, ny, nx, used | (1<<4*ny+nx));
            }
        }
    }

    const int INF = 1<<28;

    void solve() {
        count.clear(); count.resize(N, 0);
        map<char, bool> found;
        for (int y = 0; y < 4; y++) {
            for (int x = 0; x < 4; x++) {
                found[F[y][x]] = true;
            }
        }
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < ws[i].size(); j++) {
                if (not found[ws[i][j]]) {
                    goto next;
                }
            }
            for (int y = 0; y < 4; y++) {
                for (int x = 0; x < 4; x++) {
                    if (F[y][x] == ws[i][0]) {
                        dfs(i, 1, y, x, 1<<(4*y+x));
                    }
                }
            }
            next:;
        }
        auto dp = vector<vector<int>>(2, vector<int>(T + 1, -INF));
        dp[0][0] = 0;
        for (int i = 1; i <= N; i++) {
            int l = ws[i - 1].size();
            for (int t = 0; t <= T; t++) {
                if (dp[0][t] >= 0) {
                    for (int k = 0; k <= count[i - 1]; k++) {
                        int x = t + k * l;
                        if (x > T) break;
                        dp[1][x] = max(dp[1][x], dp[0][t] + k * ss[i - 1]);
                    }
                }
            }
            swap(dp[0], dp[1]);
        }
        int ans = 0;
        for (int t = 0; t <= T; t++) {
            ans = max(ans, dp[0][t]);
        }
        cout << ans << endl;
    }
}

int main() {
    input(); solve();
    return 0;
}
accuracy: 1
time_ms: 620
memory_kb: 3316
final_rank: 12

code_snippet: #include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int N, T, a[107], c[107], l[107], used[4][4], dp[10009]; string s[107], m[4];
int rec(int x, int y, int d, int v) {
	if (d == l[v]) return 1;
	int ret = 0;
	for (int i = -1; i <= 1; i++) {
		for (int j = -1; j <= 1; j++) {
			int tx = x + j, ty = y + i;
			if (0 <= tx && tx <= 3 && 0 <= ty && ty <= 3 && !used[ty][tx] && m[ty][tx] == s[v][d]) {
				used[ty][tx] = 1;
				ret += rec(tx, ty, d + 1, v);
				used[ty][tx] = 0;
			}
		}
	}
	return ret;
}
int main() {
	cin >> N;
	for (int i = 0; i < N; i++) cin >> s[i] >> a[i], l[i] = s[i].size();
	for (int i = 0; i < 4; i++) cin >> m[i];
	cin >> T;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < 4; j++) {
			for (int k = 0; k < 4; k++) {
				if (m[j][k] == s[i][0]) {
					used[j][k] = 1;
					c[i] += rec(k, j, 1, i);
					used[j][k] = 0;
				}
			}
		}
	}
	for (int i = 0; i < N; i++) {
		int x = c[i];
		for (int j = 1; x > 0; j <<= 1) {
			int mul = min(j, x);
			for (int k = T; k >= l[i] * mul; k--) dp[k] = max(dp[k], dp[k - l[i] * mul] + a[i] * mul);
			x -= mul;
		}
	}
	cout << dp[T] << endl;
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3236
final_rank: 3

code_snippet: #include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int N, T, a[107], c[107], used[4][4]; string s[107], m[4];
int rec(int x, int y, int d, int v) {
	if (d == s[v].size()) return 1;
	int ret = 0;
	for (int i = -1; i <= 1; i++) {
		for (int j = -1; j <= 1; j++) {
			int tx = x + j, ty = y + i;
			if (0 <= tx && tx <= 3 && 0 <= ty && ty <= 3 && !used[ty][tx] && m[ty][tx] == s[v][d]) {
				used[ty][tx] = 1;
				ret += rec(tx, ty, d + 1, v);
				used[ty][tx] = 0;
			}
		}
	}
	return ret;
}
int main() {
	cin >> N;
	for (int i = 0; i < N; i++) cin >> s[i] >> a[i];
	for (int i = 0; i < 4; i++) cin >> m[i];
	cin >> T;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < 4; j++) {
			for (int k = 0; k < 4; k++) {
				if (m[j][k] == s[i][0]) {
					used[j][k] = 1;
					c[i] += rec(k, j, 1, i);
					used[j][k] = 0;
				}
			}
		}
	}
	int dp[10009] = { 0 };
	for (int i = 0; i < N; i++) {
		int x = c[i];
		for (int j = 1; x > 0; j <<= 1) {
			int mul = min(j, x);
			for (int k = T; k >= s[i].size() * mul; k--) dp[k] = max(dp[k], dp[k - s[i].size() * mul] + a[i] * mul);
			x -= mul;
		}
	}
	cout << dp[T] << endl;
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3200
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define for_(i,a,b) for (int i=(a);i<(b);++i)

int N, score[111], T, memo[4][4][1 << 16], id, num[111], dp[100010];
string word[111], grid[4];

int dx[8] = {-1,-1,-1,0,1,1,1,0};
int dy[8] = {1,0,-1,-1,-1,0,1,1};

inline int gridId(int x, int y) { return (y << 2) + x; }

int rec(int x, int y, int bit) {
	int s = __builtin_popcount(bit);
	
	if (s >= (int)word[id].size()) return 1;
	if (memo[y][x][bit] >= 0) return memo[y][x][bit];
	
	int& res = memo[y][x][bit];
	res = 0;
	
	for_(d,0,8) {
		int nx = x + dx[d], ny = y + dy[d];
		if (nx < 0 || 4 <= nx || ny < 0 || 4 <= ny) continue;
		if (bit >> gridId(nx, ny) & 1) continue;
		if (grid[ny][nx] == word[id][s]) res += rec(nx, ny, bit | (1 << gridId(nx, ny)));
	}
	
	return res;
}

void solve() {
	memset(num, 0, sizeof(num));
		
	for_(i,0,N) {
		id = i;
		memset(memo, -1, sizeof(memo));
		
		for_(y,0,4) for_(x,0,4)	{
			if (grid[y][x] != word[i][0]) continue;
			num[i] += rec(x, y, 1 << gridId(x, y));
		}
	}
	
	memset(dp, 0, sizeof(dp));
	
	for_(i,0,N) {
		int m = num[i], len = word[i].size();
		
		for (int k = 1; m > 0; k <<= 1) {
			int mul = min(k, m);
			for (int j = T; j >= len * mul; --j) {
				dp[j] = max(dp[j], dp[j - len * mul] + score[i] * mul);
			}
			m -= mul;
		}
	}
	
	cout << dp[T] << endl;
}

int main() {
	cin >> N;
	for_(i,0,N) cin >> word[i] >> score[i];
	for_(i,0,4) cin >> grid[i];
	cin >> T;
	solve();
}
accuracy: 1
time_ms: 50
memory_kb: 7704
final_rank: 9

code_snippet: /*
 * 2519.cc: English
 */

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<deque>
#include<algorithm>
#include<numeric>
#include<utility>
#include<complex>
#include<functional>
 
using namespace std;

/* constant */

const int MAX_N = 100;
const int H = 4, W = 4;
const int MAX_T = 10000;

const int dxs[] = {1, 1, 0, -1, -1, -1, 0, 1};
const int dys[] = {0, -1, -1, -1, 0, 1, 1, 1};

/* typedef */

/* global variables */

string words[MAX_N], flds[H];
int scs[MAX_N], wns[MAX_N], dp[2][MAX_T + 1];
bool used[H][W];

/* subroutines */

int rec(string &s, int k, int ux, int uy) {
  int sn = s.size();
  if (k >= sn - 1) return 1;

  int cnt = 0;
  used[uy][ux] = true;

  for (int di = 0; di < 8; di++) {
    int vx = ux + dxs[di], vy = uy + dys[di];
    if (vx >= 0 && vx < W && vy >= 0 && vy < H &&
	flds[vy][vx] == s[k + 1] && ! used[vy][vx])
      cnt += rec(s, k + 1, vx, vy);
  }

  used[uy][ux] = false;
  return cnt;
}

/* main */

int main() {
  int n;
  cin >> n;

  for (int i = 0; i < n; i++) cin >> words[i] >> scs[i];
  for (int i = 0; i < H; i++) cin >> flds[i];

  int t;
  cin >> t;

  for (int i = 0; i < n; i++) {
    string &wdi = words[i];
    wns[i] = 0;
    for (int y = 0; y < H; y++)
      for (int x = 0; x < W; x++)
	if (flds[y][x] == wdi[0]) wns[i] += rec(wdi, 0, x, y);
    //printf("wns[%d] = %d\n", i, wns[i]);
  }

  memset(dp, -1, sizeof(dp));
  dp[0][0] = 0;
  int cur = 0, nxt = 1;

  for (int i = 0; i < n; i++) {
    int &wn = wns[i];
    int &si = scs[i], s = si;
    int wi = words[i].size(), w = wi;

    memcpy(dp[nxt], dp[cur], sizeof(dp[0]));

    for (int k = 0; k < wn && w <= t; k++, s += si, w += wi) {
      int maxj = t - w;
      for (int j = 0; j <= maxj; j++)
	if (dp[cur][j] >= 0) {
	  int d = dp[cur][j] + s;
	  if (dp[nxt][j + w] < d) dp[nxt][j + w] = d;
	}
    }
    cur ^= 1, nxt ^= 1;
  }

  int maxdp = 0;
  for (int i = 0; i <= t; i++)
    if (maxdp < dp[cur][i]) maxdp = dp[cur][i];
  printf("%d\n", maxdp);
  return 0;
}
accuracy: 1
time_ms: 570
memory_kb: 1300
final_rank: 11

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)

using namespace std;

const int MAX_N = 101;
const int IINF = INT_MAX;

int N,T;
string s[MAX_N];
int score[MAX_N],cnt[MAX_N];
char a[6][6];
bool used[6][6];
int dp[10010];

void dfs(int x,int y,int depth,int limit,int index){
  if( depth >= limit ) {
    ++cnt[index];
    return;
  }
  REP(dx,-1,2){
    REP(dy,-1,2){
      if( dx == 0 && dy == 0 ) continue;
      int nx = x + dx, ny = y + dy;
      if( !( 0 <= nx && nx < 4 && 0 <= ny && ny < 4 ) ) continue;
      if( used[ny][nx] || a[ny][nx] != s[index][depth] ) continue;
      used[ny][nx] = true;
      dfs(nx,ny,depth+1,limit,index);
      used[ny][nx] = false;
    }
  }
}

void compute(){
  rep(i,N) rep(y,4) rep(x,4) if( a[y][x] == s[i][0] ) {
    used[y][x] = true;
    dfs(x,y,1,(int)s[i].size(),i);
    used[y][x] = false;
  }

  rep(i,T+1) dp[i] = -IINF;
  dp[0] = 0;
  int maxi = 0;
  rep(i,N){
    int len = (int)s[i].size();
    for(int t=T;t>=0;t--) if( dp[t] != -IINF ) {
      for(int use=0;t+use*len<=T&&use<=cnt[i];use++){
        dp[t+use*len] = max(dp[t+use*len],dp[t]+use*score[i]);
        maxi = max(maxi,dp[t+use*len]);
      }
    }
  }
  cout << maxi << endl;
}

int main(){
  cin >> N;
  rep(i,N) cin >> s[i] >> score[i];
  rep(i,4) {
    string line;
    cin >> line;
    rep(j,4) a[i][j] = line[j];
  }
  cin >> T;
  compute();
  return 0;
}
accuracy: 1
time_ms: 960
memory_kb: 1252
final_rank: 14

code_snippet: #define _USE_MATH_DEFINES
#define INF 0x3f3f3f3f

#include <iostream>
#include <cstdio>
#include <sstream>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <limits>
#include <map>
#include <string>
#include <cstring>
#include <set>
#include <deque>
#include <bitset>
#include <list>
#include <cctype>
#include <utility>
  
using namespace std;
  
typedef long long ll;
typedef pair <int,int> P;
typedef pair <int,P> PP;
  
static const double EPS = 1e-8;
  
int tx[] = {+0,+1,+1,+1,+0,-1,-1,-1};
int ty[] = {-1,-1,+0,+1,+1,+1,+0,-1};

map<string,int> freq;

void dfs(int x,int y,
	 string str,
	 int visited,
	 char stage[4][4],
	 const set<string>& keywords){
  str += stage[y][x];
  visited |= (1<<(4*y+x));
  if(keywords.count(str) > 0){
    freq[str]++;
  }

  if(__builtin_popcount((visited)) >= 8) return;

  for(int i=0;i<8;i++){
    int dx = x + tx[i];
    int dy = y + ty[i];
    if(dx < 0 || dx >= 4 || dy < 0 || dy >= 4) continue;
    int idx = dy * 4 + dx;
    if(visited & (1<<idx)) continue;
    dfs(dx,dy,str,visited,stage,keywords);
  }
}



int main(){
  int N;
  while(~scanf("%d",&N)){
    freq.clear();
    char stage[4][4];

    set<string> keywords;
    vector<string> keywords_v;
    map<string,int> score_table;
    int dp[10001];

    for(int i=0;i<N;i++){
      string word;
      int score;
      cin >> word >> score;
      score_table[word] = score;
      keywords.insert(word);
      keywords_v.push_back(word);
    }
    for(int y=0;y<4;y++){
      string line;
      cin >> line;
      for(int x=0;x<4;x++){
	stage[y][x] = line[x];
      }
    }

    int time_limit;
    scanf("%d",&time_limit);
    memset(dp,-1,sizeof(dp));
    for(int y=0;y<4;y++){
      for(int x=0;x<4;x++){
	dfs(x,y,"",0,stage,keywords);
      }
    }

    dp[0] = 0;
    for(int key_idx=0;key_idx < keywords_v.size();key_idx++){
      const string& key = keywords_v[key_idx];
      int cost = key.length();
      int score = score_table[key];

      int scalar = 1;
      int capacity = freq[key];
      for(;
	  scalar <= capacity;
	  capacity -= scalar,scalar *= 2){

	for(int next_time=time_limit;next_time - cost * scalar>=0;next_time--){
	  int from_time = next_time - cost * scalar;
	  if(dp[from_time] == -1) continue;
	  dp[next_time] = max(dp[from_time] + score * scalar,
			      dp[next_time]);
	}
      }

      if(capacity){
	for(int next_time=time_limit;next_time - cost * capacity>=0;next_time--){
	  int from_time = next_time - cost * capacity;
	  if(dp[from_time] == -1) continue;
	  dp[next_time] = max(dp[from_time] + score * capacity,
			      dp[next_time]);
	}
      }
    }

    int max_score = 0;
    for(int time = time_limit; time >=0; time--){
      max_score = max(dp[time],max_score);
    }
    printf("%d\n",max_score);
  }
}
accuracy: 1
time_ms: 80
memory_kb: 1356
final_rank: 1