Problem:
Problem J: Yu-kun Likes a lot of Money
Background
会津大学付属幼稚園はプログラミングが大好きな子供が集まる幼稚園である。園児の一人であるゆう君は、プログラミングと同じくらいお金が大好きだ。ゆう君は、今日もお金を稼ぐために財宝の眠る島を訪れた。ゆう君は事前に財宝のありかの描かれた地図を手に入れている。その地図をもとに出来るだけ多くのお金を稼ぎたい。ゆう君は最大でどのくらいお金を手に入れることができるだろうか？
Problem
地図、ゆう君の初期位置、財宝の種類とそれらから得られるお金、そして小さい岩を破壊するために必要な費用の情報が与えられる。地図の情報は
h
マス ×
w
マスのフィールドとして与えられる。地図の各マスに書かれている文字とその意味は次の通りである。
'@' : ゆう君が最初にいる位置を表す。ゆう君が移動した後は道と同じように扱う。
'.' : 道を表す。このマスは自由に通ることができ費用もかからない。
'#' : 大きな岩を表す。このマスは通ることができない。
'*' : 小さな岩を表す。一定の金額を支払うことで壊すことができる。壊した後は道になる。
'0','1',...,'9','a','b',...,'z','A','B',...,'Z' : 財宝があるマスを表す。このマスを訪れることでそこに書かれている文字に対応する財宝の金額分のお金を得る。ただしお金を得ることが出来るのは最初に訪れた時のみである。
ゆう君は１回の移動で隣接する上下左右のいずれかのマスに移動することができる。
ただし、地図の外へ出るような移動はできない。
後払いをすることができるため、小さな岩を壊す際にそれに必要な金額をその時に所持している必要はない。そのため、ゆう君は最終的に小さな岩を壊す際にかかった金額の総和以上のお金を得ている必要がある。
ゆう君が得られる最大の金額を出力せよ。
Input
入力は以下の形式で与えられる。
h
w
n
r
c
1,1
c
1,2
…
c
1,w
c
2,1
c
2,2
…
c
2,w
…
c
h,1
c
h,2
…
c
h,w
m
1
v
1
m
2
v
2
…
m
n
v
n
１行目に地図の縦の長さ
h
,横の長さ
w
,地図に含まれる財宝の数
n
,小さな岩を破壊するためにかかる費用
r
が空白区切りで与えられる。
続く
h
行に地図を表す各マスの情報
c
i,j
が
w
個与えられる。 ( 1 ≤
i
≤
h
, 1 ≤
j
≤
w
)
続く
n
行に財宝の種類
m
k
とその財宝の金額
v
k
が空白区切りで与えられる。 ( 1 ≤
k
≤
n
)
Constraints
入力は以下の制約を満たす。
1 ≤
h
,
w
≤ 8
0 ≤
n
≤ min(
h
×
w
-1,62) ただし、min(
a
,
b
)は
a
,
b
の最小値を表す
1 ≤
v
i
≤ 10
5
( 1 ≤
i
≤
n
)
1 ≤
r
≤ 10
5
c
j,k
,
m
l
を除く全ての入力は整数として与えられる ( 1 ≤
j
≤
h
, 1 ≤
k
≤
w
, 1 ≤
l
≤
n
)
地図にはちょうどひとつ'@'が書かれている
地図にはちょうど
n
個の財宝が書かれている
地図に書かれている財宝の種類は入力で与えられた
m
l
のいずれかである
地図に同じ種類の財宝が２つ以上現れることはない
Output
ゆう君が得られる最大のお金の金額を1行に出力せよ。
Sample Input1
3 3 1 10
@0.
...
...
0 100
Sample Output1
100
Sample Input2
3 3 1 10
@#b
.#.
.#.
b 100
Sample Output2
0
Sample Input3
3 3 1 20
@*C
..*
...
C 10
Sample Output3
0

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
#define INF 1000000007
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

struct uftree{
	int par[25];
	int rank[25];
	uftree(){
	}
	void init(int n){
		for(int i=0;i<n;i++){
			par[i]=i;
			rank[i]=0;
		}
	}
	int find(int x){
		if(par[x]==x)return x;
		return par[x]=find(par[x]);
	}

	void unite(int x,int y){
		x=find(x);
		y=find(y);
		if(x==y)return;
		if(rank[x]<rank[y]){
			par[x]=y;
		}else{
			if(rank[x]==rank[y])rank[x]++;
			par[y]=x;
		}
	}

	bool same(int x,int y){
		return find(x)==find(y);
	}
};


int h,w,n,R;
vector<int> vec;

int tmp[8];
int ki[8];
int id[1<<25];

void dfs(int x,int c){
	if(x==w){
		int val=0;
		for(int i=0;i<w;i++){
			val+=tmp[i]*ki[i];
		}
		vec.push_back(val);
	}else{
		if(x==0){
			tmp[0]=0;
			dfs(x+1,0);
			tmp[0]=1;
			dfs(x+1,1);
		}else{
			if(tmp[x-1]==0){
				tmp[x]=c+1;
				dfs(x+1,c+1);
			}
			for(int i=0;i<=c;i++){
				tmp[x]=i;
				dfs(x+1,c);
			}
		}
	}
}

int dp[10][100000][2];

void init(){
	ki[0]=1;
	for(int i=1;i<w;i++){
		ki[i]=ki[i-1]*5;
	}
	dfs(0,0);
	sort(vec.begin(),vec.end());
	memset(id,-1,sizeof(id));
	for(int i=0;i<vec.size();i++){
		id[vec[i]]=i;
	}
}

int fie[8][8];
int val[64];
int sx,sy;

int is_person(int r){
	if(sy!=r)return 0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && sx==i)return 1;
	}
	return 0;
}

int calc_rock(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]==-1)return -1;
		if(tmp[i]>=1 && fie[r][i]==-2)sum+=R;
	}
	return sum;
}

int calc_item(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]>=1){
			sum+=val[fie[r][i]];
		}
	}
	return sum;
}

int calc_id(){
	int val=0;
	for(int i=0;i<w;i++){
		val+=tmp[i]*ki[i];
	}
	if(id[val]==-1){
		for(int i=0;i<w;i++){
			printf("%d ",tmp[i]);
		}
		printf("\n");
	}
	//assert(id[val]!=-1);
	return id[val];
}

void calc_row0(int r,int bit){
	int sz=0;
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			if(i==0){
				sz++;
				tmp[i]=sz;
			}else{
				if(tmp[i-1]!=0){
					tmp[i]=tmp[i-1];
				}else{
					sz++;
					tmp[i]=sz;
				}
			}
		}else{
			tmp[i]=0;
		}
	}
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r);
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=cost_i-cost_r;
}

int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
bool fl1[5];
bool fl2[5];
int tmp2[2][8];
int tmp3[2][8];
int colo[8];
stack<int> st;
bool po;
uftree uf;

void dfs_row(int x,int y,int sz){
	tmp3[y][x]=sz;
	if(y==0){
		if(tmp2[y][x]>0){
			uf.unite(tmp2[y][x],sz);
		}
		st.push(tmp2[y][x]);
	}else{
		po=true;
	}
	for(int i=0;i<4;i++){
		int nx=x+dx[i];
		int ny=y+dy[i];
		if(nx>=0 && nx<w && ny>=0 && ny<2){
			if(tmp2[ny][nx]!=0 && tmp3[ny][nx]==0){
				dfs_row(nx,ny,sz);
			}
		}
	}
}

void calc(int r,int index_p,int flag_p,int bit){
	memset(tmp2,0,sizeof(tmp2));
	{
		int v=vec[index_p];
		int x=0;
		while(v>0){
			if(v%5>=1)tmp2[0][x]=v%5;
			else{
				tmp2[0][x]=0;
			}
			v/=5;
			x++;
		}
	}
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			tmp2[1][i]=1;
		}
	}
	memset(fl1,false,sizeof(fl1));
	memset(fl2,false,sizeof(fl2));
	memset(tmp3,0,sizeof(tmp3));
	uf.init(6);
	for(int i=0;i<w;i++){
		if(tmp2[0][i]!=0 && tmp3[0][i]==0){
			while(st.size())st.pop();
			po=false;
			dfs_row(i,0,tmp2[0][i]);
			if(po){
				while(st.size()){
					int v=st.top();
					st.pop();
					fl2[v]=true;
				}
			}
		}
	}
	int cn=0;
	int cn2=0;
	{
		for(int i=0;i<w;i++){
			if(tmp2[0][i]>0){
				fl1[tmp2[0][i]]=true;
			}
		}
		for(int i=1;i<=4;i++){
			if(fl1[i])cn++;
			if(fl2[i])cn2++;
		}
		if(cn>=2){
			for(int i=1;i<=4;i++){
				if(fl1[i] && !fl2[i])return;
			}
		}
	}
	if(cn2>0){
		int prev=-2;
		int kero=-100;
		for(int i=0;i<w;i++){
			if(tmp3[1][i]==0 && tmp2[1][i]==1){
				if(prev+1==i){
					tmp3[1][i]=kero;
				}else{
					tmp3[1][i]=++kero;
				}
				prev=i;
			}
		}
	}else{
		for(int i=0;i<w;i++){
			if(tmp3[1][i]==0 && tmp2[1][i]==1){
				return;
			}
		}
	}
	{
		for(int i=0;i<w;i++){
			if(tmp3[1][i]>0){
				tmp3[1][i]=uf.find(tmp3[1][i]);
			}
		}
	}
	{
		vector<int> vt;
		for(int i=0;i<w;i++){
			tmp[i]=tmp3[1][i];
			if(tmp[i]!=0)vt.push_back(tmp[i]);
		}
		vt.push_back(-105);
		sort(vt.begin(),vt.end());
		vt.erase(unique(vt.begin(),vt.end()),vt.end());
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			tmp[i]=lower_bound(vt.begin(),vt.end(),tmp[i])-vt.begin();
		}
		map<int,int> mp;
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			if(mp.find(tmp[i])==mp.end()){
				mp[tmp[i]]=mp.size();
			}
		}
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			tmp[i]=mp[tmp[i]];
		}
	}
	
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r)|flag_p;
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=max(dp[r+1][index][flag],dp[r][index_p][flag_p]+cost_i-cost_r);
	if(dp[r][index_p][flag_p]+cost_i-cost_r>=0){
		/*
		printf("r=%d %d %d-> index=%d flag=%d cost=%d\n",r,index_p,flag_p,index,flag,dp[r][index_p][flag_p]+cost_i-cost_r);
		for(int i=0;i<2;i++){
			for(int j=0;j<w;j++){
				printf("%d ",tmp2[i][j]);
			}
			printf("\n");	
		}
		for(int j=0;j<w;j++){
			printf("%d ",tmp[j]);
		}
		printf("\n");
		*/
	}
}

bool is_ok(int v){
	while(v>0){
		if(v%5>=2)return false;
		v/=5;
	}
	return true;
}

int main(void){
	scanf("%d%d%d%d",&h,&w,&n,&R);
	init();
	for(int i=0;i<h;i++){
		string s;
		cin >> s;
		for(int j=0;j<w;j++){
			if(s[j]>='0' && s[j]<='9'){
				fie[i][j]=(s[j]-'0')+1;
			}
			if(s[j]>='a' && s[j]<='z'){
				fie[i][j]=(s[j]-'a')+11;
			}
			if(s[j]>='A' && s[j]<='Z'){
				fie[i][j]=(s[j]-'A')+37;
			}
			if(s[j]=='@'){
				sx=j;
				sy=i;
			}
			if(s[j]=='#'){
				fie[i][j]=-1;
			}
			if(s[j]=='*'){
				fie[i][j]=-2;
			}
		}
	}
	for(int i=0;i<n;i++){
		char c;
		int a;
		scanf(" %c%d",&c,&a);
		if(c>='0' && c<='9'){
			val[(c-'0')+1]=a;
		}
		if(c>='a' && c<='z'){
			val[(c-'a')+11]=a;
		}
		if(c>='A' && c<='Z'){
			val[(c-'A')+37]=a;
		}
	}
	for(int i=0;i<=h;i++){
		for(int j=0;j<vec.size();j++){
			for(int k=0;k<2;k++){
				dp[i][j][k]=-INF;
			}
		}
	}
	for(int j=0;j<h;j++){
		for(int i=0;i<(1<<w);i++){
			calc_row0(j,i);
		}
	}
	for(int i=1;i<h;i++){
		for(int j=1;j<vec.size();j++){
			for(int k=0;k<2;k++){
				if(dp[i][j][k]==-INF)continue;
				for(int l=0;l<(1<<w);l++){
					calc(i,j,k,l);
				}
			}
		}
	}
	int ans=0;
	for(int j=1;j<=h;j++){
		for(int i=0;i<vec.size();i++){
			if(is_ok(vec[i])){
				ans=max(ans,dp[j][i][1]);
			}
		}
	}
	
	printf("%d\n",ans);
	return 0;
}
accuracy: 1
time_ms: 910
memory_kb: 134596
final_rank: 1

code_snippet: #include <iostream>
#include <vector>
#include <utility>
#include <queue>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>

int main() {
  std::priority_queue<std::tuple<int, int, std::vector<int>>> queue;

  int h, w, n, r;
  char c[64];
  int st;
  std::unordered_map<char, int> m;
  std::cin >> h >> w >> n >> r;
  for (int y = 0; y < h; ++y) {
    for (int x = 0; x < w; ++x) {
      std::cin >> c[x + w * y];
      if (c[x + w * y] == '@') {
        st = x + w * y;
      }
    }
  }
  std::vector<int> cost(h * w, -r * h * w - 1);
  for (int i = 0; i < n; ++i) {
    char key;
    int gold;
    std::cin >> key >> gold;
    m.emplace(key, gold);
  }
  queue.emplace(0, st, std::vector<int>(h * w, 0));
  int max_score = 0;
  while (!queue.empty()) {
    auto item = queue.top();
    queue.pop();
    auto score = std::get<0>(item);
    auto pos = std::get<1>(item);
    auto stayed = std::get<2>(item);
    int x = pos % w;
    int y = pos / w;
    for (int j : {0, 1}) {
      for (int k : {-1, 1}) {
        int dx, dy;
        if (j == 0) {
          dx = 0;
          dy = k;
        } else {
          dx = k;
          dy = 0;
        }
        int new_x = x + dx;
        int new_y = y + dy;
        if (new_x >= 0 && new_x < w && new_y >= 0 && new_y < h) {
          auto stayed_copied = stayed;
          int new_pos = new_x + new_y * w;
          if (stayed_copied[new_pos] >= 2) {
            continue;
          }
          char field = c[new_pos];
          if (field == '#') {
            continue;
          }
          int new_score = score;
          if (stayed_copied[new_pos] == 0) {
            if (field == '*') {
              new_score -= r;
            } else if (field != '.' && field != '@') {
              new_score += m[field];
            }
          }
          if (cost[new_pos] <= new_score) {
            stayed_copied[new_pos] += 1;
            cost[new_pos] = new_score;
            queue.emplace(new_score, new_pos, stayed_copied);
            if (max_score < new_score) {
              max_score = new_score;
            }
          }
        }
      }
    }
  }
  std::cout << max_score << std::endl;
  return 0;
}
accuracy: 0.3076923076923077
time_ms: 10
memory_kb: 3284
final_rank: 5

code_snippet: #include <bits/stdc++.h>
#define INF 1000000007
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

struct uftree{
	int par[25];
	int rank[25];
	uftree(){
	}
	void init(int n){
		for(int i=0;i<n;i++){
			par[i]=i;
			rank[i]=0;
		}
	}
	int find(int x){
		if(par[x]==x)return x;
		return par[x]=find(par[x]);
	}

	void unite(int x,int y){
		x=find(x);
		y=find(y);
		if(x==y)return;
		if(rank[x]<rank[y]){
			par[x]=y;
		}else{
			if(rank[x]==rank[y])rank[x]++;
			par[y]=x;
		}
	}

	bool same(int x,int y){
		return find(x)==find(y);
	}
};


int h,w,n,R;
vector<int> vec;

int tmp[8];
int ki[8];
int id[1<<25];

void dfs(int x,int c){
	if(x==w){
		int val=0;
		for(int i=0;i<w;i++){
			val+=tmp[i]*ki[i];
		}
		vec.push_back(val);
	}else{
		if(x==0){
			tmp[0]=0;
			dfs(x+1,0);
			tmp[0]=1;
			dfs(x+1,1);
		}else{
			if(tmp[x-1]==0){
				tmp[x]=c+1;
				dfs(x+1,c+1);
			}
			for(int i=0;i<=c;i++){
				tmp[x]=i;
				dfs(x+1,c);
			}
		}
	}
}

int dp[10][100000][2];

void init(){
	ki[0]=1;
	for(int i=1;i<w;i++){
		ki[i]=ki[i-1]*5;
	}
	dfs(0,0);
	sort(vec.begin(),vec.end());
	memset(id,-1,sizeof(id));
	for(int i=0;i<vec.size();i++){
		id[vec[i]]=i;
	}
}

int fie[8][8];
int val[64];
int sx,sy;

int is_person(int r){
	if(sy!=r)return 0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && sx==i)return 1;
	}
	return 0;
}

int calc_rock(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]==-1)return -1;
		if(tmp[i]>=1 && fie[r][i]==-2)sum+=R;
	}
	return sum;
}

int calc_item(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]>=1){
			sum+=val[fie[r][i]];
		}
	}
	return sum;
}

int calc_id(){
	int val=0;
	for(int i=0;i<w;i++){
		val+=tmp[i]*ki[i];
	}
	if(id[val]==-1){
		for(int i=0;i<w;i++){
			printf("%d ",tmp[i]);
		}
		printf("\n");
	}
	//assert(id[val]!=-1);
	return id[val];
}

void calc_row0(int r,int bit){
	int sz=0;
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			if(i==0){
				sz++;
				tmp[i]=sz;
			}else{
				if(tmp[i-1]!=0){
					tmp[i]=tmp[i-1];
				}else{
					sz++;
					tmp[i]=sz;
				}
			}
		}else{
			tmp[i]=0;
		}
	}
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r);
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=cost_i-cost_r;
}

int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
bool fl1[5];
bool fl2[5];
int tmp2[2][8];
int tmp3[2][8];
int colo[8];
stack<int> st;
bool po;
uftree uf;

void dfs_row(int x,int y,int sz){
	tmp3[y][x]=sz;
	if(y==0){
		if(tmp2[y][x]>0){
			uf.unite(tmp2[y][x],sz);
		}
		st.push(tmp2[y][x]);
	}else{
		po=true;
	}
	for(int i=0;i<4;i++){
		int nx=x+dx[i];
		int ny=y+dy[i];
		if(nx>=0 && nx<w && ny>=0 && ny<2){
			if(tmp2[ny][nx]!=0 && tmp3[ny][nx]==0){
				dfs_row(nx,ny,sz);
			}
		}
	}
}

void calc(int r,int index_p,int flag_p,int bit){
	memset(tmp2,0,sizeof(tmp2));
	{
		int v=vec[index_p];
		int x=0;
		while(v>0){
			if(v%5>=1)tmp2[0][x]=v%5;
			else{
				tmp2[0][x]=0;
			}
			v/=5;
			x++;
		}
	}
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			tmp2[1][i]=1;
		}
	}
	memset(fl1,false,sizeof(fl1));
	memset(fl2,false,sizeof(fl2));
	memset(tmp3,0,sizeof(tmp3));
	uf.init(6);
	for(int i=0;i<w;i++){
		if(tmp2[0][i]!=0 && tmp3[0][i]==0){
			while(st.size())st.pop();
			po=false;
			dfs_row(i,0,tmp2[0][i]);
			if(po){
				while(st.size()){
					int v=st.top();
					st.pop();
					fl2[v]=true;
				}
			}
		}
	}
	int cn=0;
	int cn2=0;
	{
		for(int i=0;i<w;i++){
			if(tmp2[0][i]>0){
				fl1[tmp2[0][i]]=true;
			}
		}
		for(int i=1;i<=4;i++){
			if(fl1[i])cn++;
			if(fl2[i])cn2++;
		}
		if(cn>=2){
			for(int i=1;i<=4;i++){
				if(fl1[i] && !fl2[i])return;
			}
		}
	}
	if(cn2>0){
		int prev=-2;
		int kero=-100;
		for(int i=0;i<w;i++){
			if(tmp3[1][i]==0 && tmp2[1][i]==1){
				if(prev+1==i){
					tmp3[1][i]=kero;
				}else{
					tmp3[1][i]=++kero;
				}
				prev=i;
			}
		}
	}else{
		for(int i=0;i<w;i++){
			if(tmp3[1][i]==0 && tmp2[1][i]==1){
				return;
			}
		}
	}
	{
		for(int i=0;i<w;i++){
			if(tmp3[1][i]>0){
				tmp3[1][i]=uf.find(tmp3[1][i]);
			}
		}
	}
	{
		vector<int> vt;
		for(int i=0;i<w;i++){
			tmp[i]=tmp3[1][i];
			if(tmp[i]!=0)vt.push_back(tmp[i]);
		}
		vt.push_back(-105);
		sort(vt.begin(),vt.end());
		vt.erase(unique(vt.begin(),vt.end()),vt.end());
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			tmp[i]=lower_bound(vt.begin(),vt.end(),tmp[i])-vt.begin();
		}
		map<int,int> mp;
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			if(mp.find(tmp[i])==mp.end()){
				mp[tmp[i]]=mp.size();
			}
		}
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			tmp[i]=mp[tmp[i]];
		}
	}
	
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r)|flag_p;
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=max(dp[r+1][index][flag],dp[r][index_p][flag_p]+cost_i-cost_r);
	if(dp[r][index_p][flag_p]+cost_i-cost_r>=0){
		/*
		printf("r=%d %d %d-> index=%d flag=%d cost=%d\n",r,index_p,flag_p,index,flag,dp[r][index_p][flag_p]+cost_i-cost_r);
		for(int i=0;i<2;i++){
			for(int j=0;j<w;j++){
				printf("%d ",tmp2[i][j]);
			}
			printf("\n");	
		}
		for(int j=0;j<w;j++){
			printf("%d ",tmp[j]);
		}
		printf("\n");
		*/
	}
}

bool is_ok(int v){
	while(v>0){
		if(v%5>=2)return false;
		v/=5;
	}
	return true;
}

int main(void){
	scanf("%d%d%d%d",&h,&w,&n,&R);
	init();
	for(int i=0;i<h;i++){
		string s;
		cin >> s;
		for(int j=0;j<w;j++){
			if(s[j]>='0' && s[j]<='9'){
				fie[i][j]=(s[j]-'0')+1;
			}
			if(s[j]>='a' && s[j]<='z'){
				fie[i][j]=(s[j]-'a')+11;
			}
			if(s[j]>='A' && s[j]<='Z'){
				fie[i][j]=(s[j]-'A')+37;
			}
			if(s[j]=='@'){
				sx=j;
				sy=i;
			}
			if(s[j]=='#'){
				fie[i][j]=-1;
			}
			if(s[j]=='*'){
				fie[i][j]=-2;
			}
		}
	}
	for(int i=0;i<n;i++){
		char c;
		int a;
		scanf(" %c%d",&c,&a);
		if(c>='0' && c<='9'){
			val[(c-'0')+1]=a;
		}
		if(c>='a' && c<='z'){
			val[(c-'a')+11]=a;
		}
		if(c>='A' && c<='Z'){
			val[(c-'A')+37]=a;
		}
	}
	for(int i=0;i<=h;i++){
		for(int j=0;j<vec.size();j++){
			for(int k=0;k<2;k++){
				dp[i][j][k]=-INF;
			}
		}
	}
	for(int j=0;j<h;j++){
		for(int i=0;i<(1<<w);i++){
			calc_row0(j,i);
		}
	}
	for(int i=1;i<h;i++){
		for(int j=1;j<vec.size();j++){
			for(int k=0;k<2;k++){
				if(dp[i][j][k]==-INF)continue;
				for(int l=0;l<(1<<w);l++){
					calc(i,j,k,l);
				}
			}
		}
	}
	int ans=0;
	for(int j=1;j<=h;j++){
		for(int i=0;i<vec.size();i++){
			if(is_ok(vec[i])){
				ans=max(ans,dp[j][i][1]);
			}
		}
	}
	
	printf("%d\n",ans);
	return 0;
}
accuracy: 1
time_ms: 920
memory_kb: 134592
final_rank: 2

code_snippet: #include <bits/stdc++.h>
#define INF 1000000007
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

struct uftree{
	int par[25];
	int rank[25];
	uftree(){
	}
	void init(int n){
		for(int i=0;i<n;i++){
			par[i]=i;
			rank[i]=0;
		}
	}
	int find(int x){
		if(par[x]==x)return x;
		return par[x]=find(par[x]);
	}

	void unite(int x,int y){
		x=find(x);
		y=find(y);
		if(x==y)return;
		if(rank[x]<rank[y]){
			par[x]=y;
		}else{
			if(rank[x]==rank[y])rank[x]++;
			par[y]=x;
		}
	}

	bool same(int x,int y){
		return find(x)==find(y);
	}
};


int h,w,n,R;
vector<int> vec;

int tmp[8];
int ki[8];
int id[1<<25];

void dfs(int x,int c){
	if(x==w){
		int val=0;
		for(int i=0;i<w;i++){
			val+=tmp[i]*ki[i];
		}
		vec.push_back(val);
	}else{
		if(x==0){
			tmp[0]=0;
			dfs(x+1,0);
			tmp[0]=1;
			dfs(x+1,1);
		}else{
			if(tmp[x-1]==0){
				tmp[x]=c+1;
				dfs(x+1,c+1);
			}
			for(int i=0;i<=c;i++){
				tmp[x]=i;
				dfs(x+1,c);
			}
		}
	}
}

int dp[10][100000][2];

void init(){
	ki[0]=1;
	for(int i=1;i<w;i++){
		ki[i]=ki[i-1]*4;
	}
	dfs(0,0);
	sort(vec.begin(),vec.end());
	memset(id,-1,sizeof(id));
	for(int i=0;i<vec.size();i++){
		id[vec[i]]=i;
	}
}

int fie[8][8];
int val[64];
int sx,sy;

int is_person(int r){
	if(sy!=r)return 0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && sx==i)return 1;
	}
	return 0;
}

int calc_rock(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]==-1)return -1;
		if(tmp[i]>=1 && fie[r][i]==-2)sum+=R;
	}
	return sum;
}

int calc_item(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]>=1){
			sum+=val[fie[r][i]];
		}
	}
	return sum;
}

int calc_id(){
	int val=0;
	for(int i=0;i<w;i++){
		val+=tmp[i]*ki[i];
	}
	if(id[val]==-1){
		for(int i=0;i<w;i++){
			printf("%d ",tmp[i]);
		}
		printf("\n");
	}
	//assert(id[val]!=-1);
	return id[val];
}

void calc_row0(int r,int bit){
	int sz=0;
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			if(i==0){
				sz++;
				tmp[i]=sz;
			}else{
				if(tmp[i-1]!=0){
					tmp[i]=tmp[i-1];
				}else{
					sz++;
					tmp[i]=sz;
				}
			}
		}else{
			tmp[i]=0;
		}
	}
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r);
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=cost_i-cost_r;
}

int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
bool fl1[5];
bool fl2[5];
int tmp2[2][8];
int tmp3[2][8];
int colo[8];
stack<int> st;
bool po;
uftree uf;

void dfs_row(int x,int y,int sz){
	tmp3[y][x]=sz;
	if(y==0){
		if(tmp2[y][x]>0){
			uf.unite(tmp2[y][x],sz);
		}
		st.push(tmp2[y][x]);
	}else{
		po=true;
	}
	for(int i=0;i<4;i++){
		int nx=x+dx[i];
		int ny=y+dy[i];
		if(nx>=0 && nx<w && ny>=0 && ny<2){
			if(tmp2[ny][nx]!=0 && tmp3[ny][nx]==0){
				dfs_row(nx,ny,sz);
			}
		}
	}
}

void calc(int r,int index_p,int flag_p,int bit){
	memset(tmp2,0,sizeof(tmp2));
	{
		int v=vec[index_p];
		int x=0;
		while(v>0){
			if(v%4>=1)tmp2[0][x]=v%4;
			else{
				tmp2[0][x]=0;
			}
			v/=4;
			x++;
		}
	}
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			tmp2[1][i]=1;
		}
	}
	memset(fl1,false,sizeof(fl1));
	memset(fl2,false,sizeof(fl2));
	memset(tmp3,0,sizeof(tmp3));
	uf.init(6);
	for(int i=0;i<w;i++){
		if(tmp2[0][i]!=0 && tmp3[0][i]==0){
			while(st.size())st.pop();
			po=false;
			dfs_row(i,0,tmp2[0][i]);
			if(po){
				while(st.size()){
					int v=st.top();
					st.pop();
					fl2[v]=true;
				}
			}
		}
	}
	int cn=0;
	int cn2=0;
	{
		for(int i=0;i<w;i++){
			if(tmp2[0][i]>0){
				fl1[tmp2[0][i]]=true;
			}
		}
		for(int i=1;i<=4;i++){
			if(fl1[i])cn++;
			if(fl2[i])cn2++;
		}
		if(cn>=2){
			for(int i=1;i<=4;i++){
				if(fl1[i] && !fl2[i])return;
			}
		}
	}
	if(cn2>0){
		int prev=-2;
		int kero=-100;
		for(int i=0;i<w;i++){
			if(tmp3[1][i]==0 && tmp2[1][i]==1){
				if(prev+1==i){
					tmp3[1][i]=kero;
				}else{
					tmp3[1][i]=++kero;
				}
				prev=i;
			}
		}
	}else{
		for(int i=0;i<w;i++){
			if(tmp3[1][i]==0 && tmp2[1][i]==1){
				return;
			}
		}
	}
	{
		for(int i=0;i<w;i++){
			if(tmp3[1][i]>0){
				tmp3[1][i]=uf.find(tmp3[1][i]);
			}
		}
	}
	{
		vector<int> vt;
		for(int i=0;i<w;i++){
			tmp[i]=tmp3[1][i];
			if(tmp[i]!=0)vt.push_back(tmp[i]);
		}
		vt.push_back(-105);
		sort(vt.begin(),vt.end());
		vt.erase(unique(vt.begin(),vt.end()),vt.end());
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			tmp[i]=lower_bound(vt.begin(),vt.end(),tmp[i])-vt.begin();
		}
		map<int,int> mp;
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			if(mp.find(tmp[i])==mp.end()){
				mp[tmp[i]]=mp.size();
			}
		}
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			tmp[i]=mp[tmp[i]];
		}
	}
	
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r)|flag_p;
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=max(dp[r+1][index][flag],dp[r][index_p][flag_p]+cost_i-cost_r);
	if(dp[r][index_p][flag_p]+cost_i-cost_r>=0){
		/*
		printf("r=%d %d %d-> index=%d flag=%d cost=%d\n",r,index_p,flag_p,index,flag,dp[r][index_p][flag_p]+cost_i-cost_r);
		for(int i=0;i<2;i++){
			for(int j=0;j<w;j++){
				printf("%d ",tmp2[i][j]);
			}
			printf("\n");	
		}
		for(int j=0;j<w;j++){
			printf("%d ",tmp[j]);
		}
		printf("\n");
		*/
	}
}

bool is_ok(int v){
	while(v>0){
		if(v%4>=2)return false;
		v/=4;
	}
	return true;
}

int main(void){
	scanf("%d%d%d%d",&h,&w,&n,&R);
	init();
	for(int i=0;i<h;i++){
		string s;
		cin >> s;
		for(int j=0;j<w;j++){
			if(s[j]>='0' && s[j]<='9'){
				fie[i][j]=(s[j]-'0')+1;
			}
			if(s[j]>='a' && s[j]<='z'){
				fie[i][j]=(s[j]-'a')+11;
			}
			if(s[j]>='A' && s[j]<='Z'){
				fie[i][j]=(s[j]-'A')+37;
			}
			if(s[j]=='@'){
				sx=j;
				sy=i;
			}
			if(s[j]=='#'){
				fie[i][j]=-1;
			}
			if(s[j]=='*'){
				fie[i][j]=-2;
			}
		}
	}
	for(int i=0;i<n;i++){
		char c;
		int a;
		scanf(" %c%d",&c,&a);
		if(c>='0' && c<='9'){
			val[(c-'0')+1]=a;
		}
		if(c>='a' && c<='z'){
			val[(c-'a')+11]=a;
		}
		if(c>='A' && c<='Z'){
			val[(c-'A')+37]=a;
		}
	}
	for(int i=0;i<=h;i++){
		for(int j=0;j<vec.size();j++){
			for(int k=0;k<2;k++){
				dp[i][j][k]=-INF;
			}
		}
	}
	for(int j=0;j<h;j++){
		for(int i=0;i<(1<<w);i++){
			calc_row0(j,i);
		}
	}
	for(int i=1;i<h;i++){
		for(int j=1;j<vec.size();j++){
			for(int k=0;k<2;k++){
				if(dp[i][j][k]==-INF)continue;
				for(int l=0;l<(1<<w);l++){
					calc(i,j,k,l);
				}
			}
		}
	}
	int ans=0;
	for(int j=1;j<=h;j++){
		for(int i=0;i<vec.size();i++){
			if(is_ok(vec[i])){
				ans=max(ans,dp[j][i][1]);
			}
		}
	}
	
	printf("%d\n",ans);
	return 0;
}
accuracy: 0.6153846153846154
time_ms: 910
memory_kb: 134576
final_rank: 3

code_snippet: #include <bits/stdc++.h>
#define INF 1000000007
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

struct uftree{
	int par[25];
	int rank[25];
	uftree(){
	}
	void init(int n){
		for(int i=0;i<n;i++){
			par[i]=i;
			rank[i]=0;
		}
	}
	int find(int x){
		if(par[x]==x)return x;
		return par[x]=find(par[x]);
	}

	void unite(int x,int y){
		x=find(x);
		y=find(y);
		if(x==y)return;
		if(rank[x]<rank[y]){
			par[x]=y;
		}else{
			if(rank[x]==rank[y])rank[x]++;
			par[y]=x;
		}
	}

	bool same(int x,int y){
		return find(x)==find(y);
	}
};


int h,w,n,R;
vector<int> vec;

int tmp[8];
int ki[8];
int id[1<<25];

void dfs(int x,int c){
	if(x==w){
		int val=0;
		for(int i=0;i<w;i++){
			val+=tmp[i]*ki[i];
		}
		vec.push_back(val);
	}else{
		if(x==0){
			tmp[0]=0;
			dfs(x+1,0);
			tmp[0]=1;
			dfs(x+1,1);
		}else{
			if(tmp[x-1]==0){
				tmp[x]=c+1;
				dfs(x+1,c+1);
				tmp[x]=c;
				dfs(x+1,c);
				tmp[x]=0;
				dfs(x+1,c);
			}else{
				tmp[x]=c;
				dfs(x+1,c);
				tmp[x]=0;
				dfs(x+1,c);
			}
		}
	}
}

int dp[10][100000][2];

void init(){
	ki[0]=1;
	for(int i=1;i<w;i++){
		ki[i]=ki[i-1]*4;
	}
	dfs(0,0);
	sort(vec.begin(),vec.end());
	memset(id,-1,sizeof(id));
	for(int i=0;i<vec.size();i++){
		id[vec[i]]=i;
	}
}

int fie[8][8];
int val[64];
int sx,sy;

int is_person(int r){
	if(sy!=r)return 0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && sx==i)return 1;
	}
	return 0;
}

int calc_rock(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]==-1)return -1;
		if(tmp[i]>=1 && fie[r][i]==-2)sum+=R;
	}
	return sum;
}

int calc_item(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]>=1){
			sum+=val[fie[r][i]];
		}
	}
	return sum;
}

int calc_id(){
	int val=0;
	for(int i=0;i<w;i++){
		val+=tmp[i]*ki[i];
	}
	if(id[val]==-1){
		for(int i=0;i<w;i++){
			printf("%d ",tmp[i]);
		}
		printf("\n");
	}
	assert(id[val]!=-1);
	return id[val];
}

void calc_row0(int r,int bit){
	int sz=0;
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			if(i==0){
				sz++;
				tmp[i]=sz;
			}else{
				if(tmp[i-1]!=0){
					tmp[i]=tmp[i-1];
				}else{
					sz++;
					tmp[i]=sz;
				}
			}
		}else{
			tmp[i]=0;
		}
	}
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r);
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=cost_i-cost_r;
}

int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
bool fl1[5];
bool fl2[5];
int tmp2[2][8];
int tmp3[2][8];
int colo[8];
stack<int> st;
bool po;
uftree uf;

void dfs_row(int x,int y,int sz){
	tmp3[y][x]=sz;
	if(y==0){
		if(tmp2[y][x]>0){
			uf.unite(tmp2[y][x],sz);
		}
		st.push(tmp2[y][x]);
	}else{
		po=true;
	}
	for(int i=0;i<4;i++){
		int nx=x+dx[i];
		int ny=y+dy[i];
		if(nx>=0 && nx<w && ny>=0 && ny<2){
			if(tmp2[ny][nx]!=0 && tmp3[ny][nx]==0){
				dfs_row(nx,ny,sz);
			}
		}
	}
}

void calc(int r,int index_p,int flag_p,int bit){
	memset(tmp2,0,sizeof(tmp2));
	{
		int v=vec[index_p];
		int x=0;
		while(v>0){
			if(v%4>=1)tmp2[0][x]=v%4;
			else{
				tmp2[0][x]=0;
			}
			v/=4;
			x++;
		}
	}
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			tmp2[1][i]=1;
		}
	}
	memset(fl1,false,sizeof(fl1));
	memset(fl2,false,sizeof(fl2));
	memset(tmp3,0,sizeof(tmp3));
	uf.init(6);
	for(int i=0;i<w;i++){
		if(tmp2[0][i]!=0 && tmp3[0][i]==0){
			while(st.size())st.pop();
			po=false;
			dfs_row(i,0,tmp2[0][i]);
			if(po){
				while(st.size()){
					int v=st.top();
					st.pop();
					fl2[v]=true;
				}
			}
		}
	}
	int cn=0;
	int cn2=0;
	{
		for(int i=0;i<w;i++){
			if(tmp2[0][i]>0){
				fl1[tmp2[0][i]]=true;
			}
		}
		for(int i=1;i<=4;i++){
			if(fl1[i])cn++;
			if(fl2[i])cn2++;
		}
		if(cn>=2){
			for(int i=1;i<=4;i++){
				if(fl1[i] && !fl2[i])return;
			}
		}
	}
	if(cn2>0){
		int prev=-2;
		int kero=-100;
		for(int i=0;i<w;i++){
			if(tmp3[1][i]==0 && tmp2[1][i]==1){
				if(prev+1==i){
					tmp3[1][i]=kero;
				}else{
					tmp3[1][i]=++kero;
				}
				prev=i;
			}
		}
	}else{
		for(int i=0;i<w;i++){
			if(tmp3[1][i]==0 && tmp2[1][i]==1){
				return;
			}
		}
	}
	{
		for(int i=0;i<w;i++){
			if(tmp3[1][i]>0){
				tmp3[1][i]=uf.find(tmp3[1][i]);
			}
		}
	}
	{
		vector<int> vt;
		for(int i=0;i<w;i++){
			tmp[i]=tmp3[1][i];
			if(tmp[i]!=0)vt.push_back(tmp[i]);
		}
		vt.push_back(-105);
		sort(vt.begin(),vt.end());
		vt.erase(unique(vt.begin(),vt.end()),vt.end());
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			tmp[i]=lower_bound(vt.begin(),vt.end(),tmp[i])-vt.begin();
		}
		map<int,int> mp;
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			if(mp.find(tmp[i])==mp.end()){
				mp[tmp[i]]=mp.size();
			}
		}
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			tmp[i]=mp[tmp[i]];
		}
	}
	
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r)|flag_p;
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=max(dp[r+1][index][flag],dp[r][index_p][flag_p]+cost_i-cost_r);
	if(dp[r][index_p][flag_p]+cost_i-cost_r>=0){
		/*
		printf("r=%d %d %d-> index=%d flag=%d cost=%d\n",r,index_p,flag_p,index,flag,dp[r][index_p][flag_p]+cost_i-cost_r);
		for(int i=0;i<2;i++){
			for(int j=0;j<w;j++){
				printf("%d ",tmp2[i][j]);
			}
			printf("\n");	
		}
		for(int j=0;j<w;j++){
			printf("%d ",tmp[j]);
		}
		printf("\n");
		*/
	}
}

bool is_ok(int v){
	while(v>0){
		if(v%4>=2)return false;
		v/=4;
	}
	return true;
}

int main(void){
	scanf("%d%d%d%d",&h,&w,&n,&R);
	init();
	for(int i=0;i<h;i++){
		string s;
		cin >> s;
		for(int j=0;j<w;j++){
			if(s[j]>='0' && s[j]<='9'){
				fie[i][j]=(s[j]-'0')+1;
			}
			if(s[j]>='a' && s[j]<='z'){
				fie[i][j]=(s[j]-'a')+11;
			}
			if(s[j]>='A' && s[j]<='Z'){
				fie[i][j]=(s[j]-'A')+37;
			}
			if(s[j]=='@'){
				sx=j;
				sy=i;
			}
			if(s[j]=='#'){
				fie[i][j]=-1;
			}
			if(s[j]=='*'){
				fie[i][j]=-2;
			}
		}
	}
	for(int i=0;i<n;i++){
		char c;
		int a;
		scanf(" %c%d",&c,&a);
		if(c>='0' && c<='9'){
			val[(c-'0')+1]=a;
		}
		if(c>='a' && c<='z'){
			val[(c-'a')+11]=a;
		}
		if(c>='A' && c<='Z'){
			val[(c-'A')+37]=a;
		}
	}
	for(int i=0;i<=h;i++){
		for(int j=0;j<vec.size();j++){
			for(int k=0;k<2;k++){
				dp[i][j][k]=-INF;
			}
		}
	}
	for(int j=0;j<h;j++){
		for(int i=0;i<(1<<w);i++){
			calc_row0(j,i);
		}
	}
	for(int i=1;i<h;i++){
		for(int j=1;j<vec.size();j++){
			for(int k=0;k<2;k++){
				for(int l=0;l<(1<<w);l++){
					calc(i,j,k,l);
				}
			}
		}
	}
	int ans=0;
	for(int j=1;j<=h;j++){
		for(int i=0;i<vec.size();i++){
			if(is_ok(vec[i])){
				ans=max(ans,dp[j][i][1]);
			}
		}
	}
	
	printf("%d\n",ans);
	return 0;
}
accuracy: 0.1282051282051282
time_ms: 30
memory_kb: 134420
final_rank: 10

code_snippet: #include <bits/stdc++.h>
#define INF 1000000007
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int h,w,n,R;
vector<int> vec;

int tmp[8];
int ki[8];
int id[1<<25];

void dfs(int x,int c){
	if(x==w){
		int val=0;
		for(int i=0;i<w;i++){
			val+=tmp[i]*ki[i];
		}
		vec.push_back(val);
	}else{
		if(x==0){
			tmp[0]=0;
			dfs(x+1,0);
			tmp[0]=1;
			dfs(x+1,1);
		}else{
			if(tmp[x-1]==0){
				tmp[x]=c+1;
				dfs(x+1,c+1);
				tmp[x]=c;
				dfs(x+1,c);
				tmp[x]=0;
				dfs(x+1,c);
			}else{
				tmp[x]=c;
				dfs(x+1,c);
				tmp[x]=0;
				dfs(x+1,c);
			}
		}
	}
}

int dp[10][100000][2];

void init(){
	ki[0]=1;
	for(int i=1;i<w;i++){
		ki[i]=ki[i-1]*4;
	}
	dfs(0,0);
	sort(vec.begin(),vec.end());
	memset(id,-1,sizeof(id));
	for(int i=0;i<vec.size();i++){
		id[vec[i]]=i;
	}
}

int fie[8][8];
int val[64];
int sx,sy;

int is_person(int r){
	if(sy!=r)return 0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && sx==i)return 1;
	}
	return 0;
}

int calc_rock(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]==-1)return -1;
		if(tmp[i]>=1 && fie[r][i]==-2)sum+=R;
	}
	return sum;
}

int calc_item(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]>=1){
			sum+=val[fie[r][i]];
		}
	}
	return sum;
}

int calc_id(){
	int val=0;
	for(int i=0;i<w;i++){
		val+=tmp[i]*ki[i];
	}
	if(id[val]==-1){
		for(int i=0;i<w;i++){
			printf("%d ",tmp[i]);
		}
		printf("\n");
	}
	assert(id[val]!=-1);
	return id[val];
}

void calc_row0(int r,int bit){
	int sz=0;
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			if(i==0){
				sz++;
				tmp[i]=sz;
			}else{
				if(tmp[i-1]!=0){
					tmp[i]=tmp[i-1];
				}else{
					sz++;
					tmp[i]=sz;
				}
			}
		}else{
			tmp[i]=0;
		}
	}
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r);
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=cost_i-cost_r;
}

int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
bool fl1[5];
bool fl2[5];
int tmp2[2][8];
int tmp3[2][8];
stack<int> st;
bool po;

void dfs_row(int x,int y,int sz){
	tmp3[y][x]=sz;
	if(y==0){
		st.push(tmp2[y][x]);
	}else{
		po=true;
	}
	for(int i=0;i<4;i++){
		int nx=x+dx[i];
		int ny=y+dy[i];
		if(nx>=0 && nx<w && ny>=0 && ny<2){
			if(tmp2[ny][nx]!=0 && tmp3[ny][nx]==0){
				dfs_row(nx,ny,sz);
			}
		}
	}
}

void calc(int r,int index_p,int flag_p,int bit){
	memset(tmp2,0,sizeof(tmp2));
	{
		int v=vec[index_p];
		int x=0;
		while(v>0){
			if(v%4>=1)tmp2[0][x]=v%4;
			else{
				tmp2[0][x]=0;
			}
			v/=4;
			x++;
		}
	}
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			tmp2[1][i]=1;
		}
	}
	memset(fl1,false,sizeof(fl1));
	memset(fl2,false,sizeof(fl2));
	memset(tmp3,0,sizeof(tmp3));
	int sz=0;
	for(int i=0;i<w;i++){
		if(tmp2[0][i]!=0 && tmp3[0][i]==0){
			while(st.size())st.pop();
			po=false;
			dfs_row(i,0,sz+1);
			if(po){
				while(st.size()){
					int v=st.top();
					st.pop();
					fl2[v]=true;
				}
			}
			sz++;
		}
	}
	int cn=0;
	int cn2=0;
	{
		for(int i=0;i<w;i++){
			if(tmp2[0][i]>0){
				fl1[tmp2[0][i]]=true;
			}
		}
		for(int i=1;i<=4;i++){
			if(fl1[i])cn++;
			if(fl2[i])cn2++;
		}
		if(cn>=2){
			for(int i=1;i<=4;i++){
				if(fl1[i] && !fl2[i])return;
			}
		}
	}
	if(cn2>0){
		int prev=-2;
		int kero=-100;
		for(int i=0;i<w;i++){
			if(tmp3[1][i]==0 && tmp2[1][i]==1){
				if(prev+1==i){
					tmp3[1][i]=kero;
				}else{
					tmp3[1][i]=++kero;
				}
				prev=i;
			}
		}
	}else{
		for(int i=0;i<w;i++){
			if(tmp3[1][i]==0 && tmp2[1][i]==1){
				return;
			}
		}
	}
	{
		vector<int> vt;
		for(int i=0;i<w;i++){
			tmp[i]=tmp3[1][i];
			if(tmp[i]!=0)vt.push_back(tmp[i]);
		}
		vt.push_back(-105);
		sort(vt.begin(),vt.end());
		vt.erase(unique(vt.begin(),vt.end()),vt.end());
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			tmp[i]=lower_bound(vt.begin(),vt.end(),tmp[i])-vt.begin();
		}
		map<int,int> mp;
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			if(mp.find(tmp[i])==mp.end()){
				mp[tmp[i]]=mp.size();
			}
		}
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			tmp[i]=mp[tmp[i]];
		}
	}
	
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r)|flag_p;
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=max(dp[r+1][index][flag],dp[r][index_p][flag_p]+cost_i-cost_r);
	/*
	if(dp[r][index_p][flag_p]+cost_i-cost_r>=0){
		printf("r=%d %d %d-> index=%d flag=%d cost=%d\n",r,index_p,flag_p,index,flag,dp[r][index_p][flag_p]+cost_i-cost_r);
		for(int i=0;i<2;i++){
			for(int j=0;j<w;j++){
				printf("%d ",tmp2[i][j]);
			}
			printf("\n");	
		}
		for(int j=0;j<w;j++){
			printf("%d ",tmp[j]);
		}
		printf("\n");
	}
	*/
}

bool is_ok(int v){
	while(v>0){
		if(v%4>=2)return false;
		v/=4;
	}
	return true;
}

int main(void){
	scanf("%d%d%d%d",&h,&w,&n,&R);
	init();
	for(int i=0;i<h;i++){
		string s;
		cin >> s;
		for(int j=0;j<w;j++){
			if(s[j]>='0' && s[j]<='9'){
				fie[i][j]=(s[j]-'0')+1;
			}
			if(s[j]>='a' && s[j]<='z'){
				fie[i][j]=(s[j]-'a')+11;
			}
			if(s[j]>='A' && s[j]<='Z'){
				fie[i][j]=(s[j]-'A')+37;
			}
			if(s[j]=='@'){
				sx=j;
				sy=i;
			}
			if(s[j]=='#'){
				fie[i][j]=-1;
			}
			if(s[j]=='*'){
				fie[i][j]=-2;
			}
		}
	}
	for(int i=0;i<n;i++){
		char c;
		int a;
		scanf(" %c%d",&c,&a);
		if(c>='0' && c<='9'){
			val[(c-'0')+1]=a;
		}
		if(c>='a' && c<='z'){
			val[(c-'a')+11]=a;
		}
		if(c>='A' && c<='Z'){
			val[(c-'A')+37]=a;
		}
	}
	for(int i=0;i<=h;i++){
		for(int j=0;j<vec.size();j++){
			for(int k=0;k<2;k++){
				dp[i][j][k]=-INF;
			}
		}
	}
	for(int j=0;j<h;j++){
		for(int i=0;i<(1<<w);i++){
			calc_row0(j,i);
		}
	}
	for(int i=1;i<h;i++){
		for(int j=1;j<vec.size();j++){
			for(int k=0;k<2;k++){
				for(int l=0;l<(1<<w);l++){
					calc(i,j,k,l);
				}
			}
		}
	}
	int ans=0;
	for(int j=1;j<=h;j++){
		for(int i=0;i<vec.size();i++){
			if(is_ok(vec[i])){
				ans=max(ans,dp[j][i][1]);
			}
		}
	}
	
	printf("%d\n",ans);
	return 0;
}
accuracy: 0.4358974358974359
time_ms: 1930
memory_kb: 134528
final_rank: 4

code_snippet: #include <bits/stdc++.h>
#define INF 1000000007
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int h,w,n,R;
vector<int> vec;

int tmp[8];
int ki[8];
int id[1<<25];

void dfs(int x,int c){
	if(x==w){
		int val=0;
		for(int i=0;i<w;i++){
			val+=tmp[i]*ki[i];
		}
		vec.push_back(val);
	}else{
		if(x==0){
			tmp[0]=0;
			dfs(x+1,0);
			tmp[0]=1;
			dfs(x+1,1);
		}else{
			if(tmp[x-1]==0){
				tmp[x]=c+1;
				dfs(x+1,c+1);
				tmp[x]=c;
				dfs(x+1,c);
				tmp[x]=0;
				dfs(x+1,c);
			}else{
				tmp[x]=c;
				dfs(x+1,c);
				tmp[x]=0;
				dfs(x+1,c);
			}
		}
	}
}

int dp[10][100000][2];

void init(){
	ki[0]=1;
	for(int i=1;i<w;i++){
		ki[i]=ki[i-1]*4;
	}
	dfs(0,0);
	sort(vec.begin(),vec.end());
	memset(id,-1,sizeof(id));
	for(int i=0;i<vec.size();i++){
		id[vec[i]]=i;
	}
}

int fie[8][8];
int val[64];
int sx,sy;

int is_person(int r){
	if(sy!=r)return 0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && sx==i)return 1;
	}
	return 0;
}

int calc_rock(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]==-1)return -1;
		if(tmp[i]>=1 && fie[r][i]==-2)sum+=R;
	}
	return sum;
}

int calc_item(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]>=1){
			sum+=val[fie[r][i]];
		}
	}
	return sum;
}

int calc_id(){
	int val=0;
	for(int i=0;i<w;i++){
		val+=tmp[i]*ki[i];
	}
	if(id[val]==-1){
		for(int i=0;i<w;i++){
			printf("%d ",tmp[i]);
		}
		printf("\n");
	}
	assert(id[val]!=-1);
	return id[val];
}

void calc_row0(int r,int bit){
	int sz=0;
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			if(i==0){
				sz++;
				tmp[i]=sz;
			}else{
				if(tmp[i-1]!=0){
					tmp[i]=tmp[i-1];
				}else{
					sz++;
					tmp[i]=sz;
				}
			}
		}else{
			tmp[i]=0;
		}
	}
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r);
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=cost_i-cost_r;
}

int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
bool fl1[5];
bool fl2[5];
int tmp2[2][8];
int tmp3[2][8];
stack<int> st;
bool po;

void dfs_row(int x,int y,int sz){
	tmp3[y][x]=sz;
	if(y==0){
		st.push(tmp2[y][x]);
	}else{
		po=true;
	}
	for(int i=0;i<4;i++){
		int nx=x+dx[i];
		int ny=y+dy[i];
		if(nx>=0 && nx<w && ny>=0 && ny<2){
			if(tmp2[ny][nx]!=0 && tmp3[ny][nx]==0){
				dfs_row(nx,ny,sz);
			}
		}
	}
}

void calc(int r,int index_p,int flag_p,int bit){
	memset(tmp2,0,sizeof(tmp2));
	{
		int v=vec[index_p];
		int x=0;
		while(v>0){
			if(v%4>=1)tmp2[0][x]=v%4;
			else{
				tmp2[0][x]=0;
			}
			v/=4;
			x++;
		}
	}
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			tmp2[1][i]=1;
		}
	}
	memset(fl1,false,sizeof(fl1));
	memset(fl2,false,sizeof(fl2));
	memset(tmp3,0,sizeof(tmp3));
	int sz=0;
	for(int i=0;i<w;i++){
		if(tmp2[0][i]!=0 && tmp3[0][i]==0){
			while(st.size())st.pop();
			po=false;
			dfs_row(i,0,sz+1);
			if(po){
				while(st.size()){
					int v=st.top();
					st.pop();
					fl2[v]=true;
				}
			}
			sz++;
		}
	}
	int cn=0;
	{
		for(int i=0;i<w;i++){
			if(tmp2[0][i]>0){
				fl1[tmp2[0][i]]=true;
			}
		}
		for(int i=1;i<=4;i++){
			if(fl1[i])cn++;
		}
		if(cn>=2){
			for(int i=1;i<=4;i++){
				if(fl1[i] && !fl2[i])return;
			}
		}
	}
	if(cn>0){
		int prev=-2;
		int kero=-100;
		for(int i=0;i<w;i++){
			if(tmp3[1][i]==0 && tmp2[1][i]==1){
				if(prev+1==i){
					tmp3[1][i]=kero;
				}else{
					tmp3[1][i]=++kero;
				}
				prev=i;
			}
		}
	}
	{
		vector<int> vt;
		for(int i=0;i<w;i++){
			tmp[i]=tmp3[1][i];
			if(tmp[i]!=0)vt.push_back(tmp[i]);
		}
		vt.push_back(-105);
		sort(vt.begin(),vt.end());
		vt.erase(unique(vt.begin(),vt.end()),vt.end());
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			tmp[i]=lower_bound(vt.begin(),vt.end(),tmp[i])-vt.begin();
		}
		map<int,int> mp;
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			if(mp.find(tmp[i])==mp.end()){
				mp[tmp[i]]=mp.size();
			}
		}
		for(int i=0;i<w;i++){
			if(tmp[i]==0)continue;
			tmp[i]=mp[tmp[i]];
		}
	}
	
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r)|flag_p;
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=max(dp[r+1][index][flag],dp[r][index_p][flag_p]+cost_i-cost_r);
	/*
	if(dp[r][index_p][flag_p]+cost_i-cost_r>=0){
		printf("r=%d %d %d-> index=%d flag=%d cost=%d\n",r,index_p,flag_p,index,flag,dp[r][index_p][flag_p]+cost_i-cost_r);
		for(int i=0;i<2;i++){
			for(int j=0;j<w;j++){
				printf("%d ",tmp2[i][j]);
			}
			printf("\n");	
		}
		for(int j=0;j<w;j++){
			printf("%d ",tmp[j]);
		}
		printf("\n");
	}
	*/
}

bool is_ok(int v){
	while(v>0){
		if(v%4>=2)return false;
		v/=4;
	}
	return true;
}

int main(void){
	scanf("%d%d%d%d",&h,&w,&n,&R);
	init();
	for(int i=0;i<h;i++){
		string s;
		cin >> s;
		for(int j=0;j<w;j++){
			if(s[j]>='0' && s[j]<='9'){
				fie[i][j]=(s[j]-'0')+1;
			}
			if(s[j]>='a' && s[j]<='z'){
				fie[i][j]=(s[j]-'a')+11;
			}
			if(s[j]>='A' && s[j]<='Z'){
				fie[i][j]=(s[j]-'A')+37;
			}
			if(s[j]=='@'){
				sx=j;
				sy=i;
			}
			if(s[j]=='#'){
				fie[i][j]=-1;
			}
			if(s[j]=='*'){
				fie[i][j]=-2;
			}
		}
	}
	for(int i=0;i<n;i++){
		char c;
		int a;
		scanf(" %c%d",&c,&a);
		if(c>='0' && c<='9'){
			val[(c-'0')+1]=a;
		}
		if(c>='a' && c<='z'){
			val[(c-'a')+11]=a;
		}
		if(c>='A' && c<='Z'){
			val[(c-'A')+37]=a;
		}
	}
	for(int i=0;i<=h;i++){
		for(int j=0;j<vec.size();j++){
			for(int k=0;k<2;k++){
				dp[i][j][k]=-INF;
			}
		}
	}
	for(int j=0;j<h;j++){
		for(int i=0;i<(1<<w);i++){
			calc_row0(j,i);
		}
	}
	
	for(int i=1;i<h;i++){
		for(int j=0;j<vec.size();j++){
			for(int k=0;k<2;k++){
				for(int l=0;l<(1<<w);l++){
					calc(i,j,k,l);
				}
			}
		}
	}
	int ans=0;
	for(int i=0;i<vec.size();i++){
		if(is_ok(vec[i])){
			ans=max(ans,dp[h][i][1]);
		}
	}
	printf("%d\n",ans);
	return 0;
}
accuracy: 0.1282051282051282
time_ms: 30
memory_kb: 134392
final_rank: 9

code_snippet: #include <bits/stdc++.h>
#define INF 1000000007
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int h,w,n,R;
vector<int> vec;

int tmp[8];
int ki[8];
int id[1<<25];

void dfs(int x,int c){
	if(x==w){
		int val=0;
		for(int i=0;i<w;i++){
			val+=tmp[i]*ki[i];
		}
		vec.push_back(val);
	}else{
		if(x==0){
			tmp[0]=0;
			dfs(x+1,0);
			tmp[0]=1;
			dfs(x+1,1);
		}else{
			if(tmp[x-1]==0){
				tmp[x]=c+1;
				dfs(x+1,c+1);
				tmp[x]=c;
				dfs(x+1,c);
				tmp[x]=0;
				dfs(x+1,c);
			}else{
				tmp[x]=c;
				dfs(x+1,c);
				tmp[x]=0;
				dfs(x+1,c);
			}
		}
	}
}

int dp[10][100000][2];

void init(){
	ki[0]=1;
	for(int i=1;i<w;i++){
		ki[i]=ki[i-1]*4;
	}
	dfs(0,0);
	sort(vec.begin(),vec.end());
	memset(id,-1,sizeof(id));
	for(int i=0;i<vec.size();i++){
		id[vec[i]]=i;
	}
}

int fie[8][8];
int val[64];
int sx,sy;

int is_person(int r){
	if(sy!=r)return 0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && sx==i)return 1;
	}
	return 0;
}

int calc_rock(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]==-1)return -1;
		if(tmp[i]>=1 && fie[r][i]==-2)sum+=R;
	}
	return sum;
}

int calc_item(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]>=1){
			sum+=val[fie[r][i]];
		}
	}
	return sum;
}

int calc_id(){
	int val=0;
	for(int i=0;i<w;i++){
		val+=tmp[i]*ki[i];
	}
	assert(id[val]!=-1);
	return id[val];
}

void calc_row0(int r,int bit){
	int sz=0;
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			if(i==0){
				sz++;
				tmp[i]=sz;
			}else{
				if(tmp[i-1]!=0){
					tmp[i]=tmp[i-1];
				}else{
					sz++;
					tmp[i]=sz;
				}
			}
		}else{
			tmp[i]=0;
		}
	}
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r);
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=cost_i-cost_r;
}

int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
bool fl1[5];
bool fl2[5];
int tmp2[2][8];
int tmp3[2][8];
stack<int> st;
bool po;

void dfs_row(int x,int y,int sz){
	tmp3[y][x]=sz;
	if(y==0){
		st.push(tmp2[y][x]);
	}else{
		po=true;
	}
	for(int i=0;i<4;i++){
		int nx=x+dx[i];
		int ny=y+dy[i];
		if(nx>=0 && nx<w && ny>=0 && ny<2){
			if(tmp2[ny][nx]!=0 && tmp3[ny][nx]==0){
				dfs_row(nx,ny,sz);
			}
		}
	}
}

void calc(int r,int index_p,int flag_p,int bit){
	memset(tmp2,0,sizeof(tmp2));
	{
		int v=vec[index_p];
		int x=0;
		while(v>0){
			if(v%4>=1)tmp2[0][x]=v%4;
			else{
				tmp2[0][x]=0;
			}
			v/=4;
			x++;
		}
	}
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			tmp2[1][i]=1;
		}
	}
	memset(fl1,false,sizeof(fl1));
	memset(fl2,false,sizeof(fl2));
	memset(tmp3,0,sizeof(tmp3));
	int sz=0;
	for(int i=0;i<w;i++){
		if(tmp2[0][i]!=0 && tmp3[0][i]==0){
			while(st.size())st.pop();
			po=false;
			dfs_row(i,0,sz+1);
			if(po){
				while(st.size()){
					int v=st.top();
					st.pop();
					fl2[v]=true;
				}
			}
			sz++;
		}
	}
	{
		for(int i=0;i<w;i++){
			if(tmp2[0][i]>0){
				fl1[tmp2[0][i]]=true;
			}
		}
		int cn=0;
		for(int i=1;i<=4;i++){
			if(fl1[i])cn++;
			//printf("%c ",fl1[i]?'y':'n');
		}
		/*
		printf("\n");
		for(int i=1;i<=4;i++){
			printf("%c ",fl2[i]?'y':'n');
		}
		printf("\n");
		*/
		if(cn>=2){
			for(int i=1;i<=4;i++){
				if(fl1[i] && !fl2[i])return;
			}
		}
	}
	{
		vector<int> vt;
		for(int i=0;i<w;i++){
			tmp[i]=tmp3[1][i];
			vt.push_back(tmp[i]);
		}
		vt.push_back(0);
		sort(vt.begin(),vt.end());
		vt.erase(unique(vt.begin(),vt.end()),vt.end());
		for(int i=0;i<w;i++){
			tmp[i]=lower_bound(vt.begin(),vt.end(),tmp[i])-vt.begin();
		}
	}
	
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r)|flag_p;
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=max(dp[r+1][index][flag],dp[r][index_p][flag_p]+cost_i-cost_r);
	/*
	printf("r=%d %d %d-> %d %d %d\n",r,index_p,flag_p,index,flag,dp[r][index_p][flag_p]+cost_i-cost_r);
	for(int i=0;i<2;i++){
		for(int j=0;j<w;j++){
			printf("%d ",tmp2[i][j]);
		}
		printf("\n");	
	}
	*/
}

bool is_ok(int v){
	while(v>0){
		if(v%4>=2)return false;
		v/=4;
	}
	return true;
}

int main(void){
	scanf("%d%d%d%d",&h,&w,&n,&R);
	init();
	for(int i=0;i<h;i++){
		string s;
		cin >> s;
		for(int j=0;j<w;j++){
			if(s[j]>='0' && s[j]<='9'){
				fie[i][j]=(s[j]-'0')+1;
			}
			if(s[j]>='a' && s[j]<='z'){
				fie[i][j]=(s[j]-'a')+11;
			}
			if(s[j]>='A' && s[j]<='Z'){
				fie[i][j]=(s[j]-'A')+37;
			}
			if(s[j]=='@'){
				sx=j;
				sy=i;
			}
			if(s[j]=='#'){
				fie[i][j]=-1;
			}
			if(s[j]=='*'){
				fie[i][j]=-2;
			}
		}
	}
	for(int i=0;i<n;i++){
		char c;
		int a;
		scanf(" %c%d",&c,&a);
		if(c>='0' && c<='9'){
			val[(c-'0')+1]=a;
		}
		if(c>='a' && c<='z'){
			val[(c-'a')+11]=a;
		}
		if(c>='A' && c<='Z'){
			val[(c-'A')+37]=a;
		}
	}
	for(int i=0;i<=h;i++){
		for(int j=0;j<vec.size();j++){
			for(int k=0;k<2;k++){
				dp[i][j][k]=-INF;
			}
		}
	}
	for(int j=0;j<h;j++){
		for(int i=0;i<(1<<w);i++){
			calc_row0(j,i);
		}
	}
	
	for(int i=1;i<h;i++){
		for(int j=0;j<vec.size();j++){
			for(int k=0;k<2;k++){
				for(int l=0;l<(1<<w);l++){
					calc(i,j,k,l);
				}
			}
		}
	}
	int ans=0;
	for(int i=0;i<vec.size();i++){
		if(is_ok(vec[i])){
			ans=max(ans,dp[h][i][1]);
		}
	}
	printf("%d\n",ans);
	return 0;
}
accuracy: 0.3076923076923077
time_ms: 20
memory_kb: 134444
final_rank: 6

code_snippet: #include <bits/stdc++.h>
#define INF 1000000007
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int h,w,n,R;
vector<int> vec;

int tmp[8];
int ki[8];
int id[1<<25];

void dfs(int x,int c){
	if(x==w){
		int val=0;
		for(int i=0;i<w;i++){
			val+=tmp[i]*ki[i];
		}
		vec.push_back(val);
	}else{
		if(x==0){
			tmp[0]=0;
			dfs(x+1,0);
			tmp[0]=1;
			dfs(x+1,1);
		}else{
			if(tmp[x-1]==0){
				tmp[x]=c+1;
				dfs(x+1,c+1);
				tmp[x]=c;
				dfs(x+1,c);
				tmp[x]=0;
				dfs(x+1,c);
			}else{
				tmp[x]=c;
				dfs(x+1,c);
				tmp[x]=0;
				dfs(x+1,c);
			}
		}
	}
}

int dp[10][100000][2];

void init(){
	ki[0]=1;
	for(int i=1;i<w;i++){
		ki[i]=ki[i-1]*4;
	}
	dfs(0,0);
	sort(vec.begin(),vec.end());
	memset(id,-1,sizeof(id));
	for(int i=0;i<vec.size();i++){
		id[vec[i]]=i;
	}
}

int fie[8][8];
int val[64];
int sx,sy;

int is_person(int r){
	if(sy!=r)return 0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && sx==i)return 1;
	}
	return 0;
}

int calc_rock(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]==-1)return -1;
		if(tmp[i]>=1 && fie[r][i]==-2)sum+=R;
	}
	return sum;
}

int calc_item(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]>=1){
			sum+=val[fie[r][i]];
		}
	}
	return sum;
}

int calc_id(){
	int val=0;
	for(int i=0;i<w;i++){
		val+=tmp[i]*ki[i];
	}
	assert(id[val]!=-1);
	return id[val];
}

void calc_row0(int r,int bit){
	int sz=0;
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			if(i==0){
				sz++;
				tmp[i]=sz;
			}else{
				if(tmp[i-1]!=0){
					tmp[i]=tmp[i-1];
				}else{
					sz++;
					tmp[i]=sz;
				}
			}
		}else{
			tmp[i]=0;
		}
	}
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r);
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[1][index][flag]=cost_i-cost_r;
}

int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
bool fl1[5];
bool fl2[5];
int tmp2[2][8];
int tmp3[2][8];
stack<int> st;
bool po;

void dfs_row(int x,int y,int sz){
	tmp3[y][x]=sz;
	if(y==0){
		st.push(tmp2[y][x]);
	}else{
		po=true;
	}
	for(int i=0;i<4;i++){
		int nx=x+dx[i];
		int ny=y+dy[i];
		if(nx>=0 && nx<w && ny>=0 && ny<2){
			if(tmp2[ny][nx]!=0 && tmp3[ny][nx]==0){
				dfs_row(nx,ny,sz);
			}
		}
	}
}

void calc(int r,int index_p,int flag_p,int bit){
	memset(tmp2,0,sizeof(tmp2));
	{
		int v=vec[index_p];
		int x=0;
		while(v>0){
			if(v%4>=1)tmp2[0][x]=v%4;
			else{
				tmp2[0][x]=0;
			}
			v/=4;
			x++;
		}
	}
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			tmp2[1][i]=1;
		}
	}
	memset(fl1,false,sizeof(fl1));
	memset(fl2,false,sizeof(fl2));
	memset(tmp3,0,sizeof(tmp3));
	int sz=0;
	for(int i=0;i<w;i++){
		if(tmp2[0][i]!=0 && tmp3[0][i]==0){
			while(st.size())st.pop();
			po=false;
			dfs_row(i,0,sz+1);
			if(po){
				while(st.size()){
					int v=st.top();
					st.pop();
					fl2[v]=true;
				}
			}
			sz++;
		}
	}
	{
		for(int i=0;i<w;i++){
			if(tmp2[0][i]>0){
				fl1[tmp2[0][i]]=true;
			}
		}
		int cn=0;
		for(int i=1;i<=4;i++){
			if(fl1[i])cn++;
			//printf("%c ",fl1[i]?'y':'n');
		}
		/*
		printf("\n");
		for(int i=1;i<=4;i++){
			printf("%c ",fl2[i]?'y':'n');
		}
		printf("\n");
		*/
		if(cn>=2){
			for(int i=1;i<=4;i++){
				if(fl1[i] && !fl2[i])return;
			}
		}
	}
	{
		vector<int> vt;
		for(int i=0;i<w;i++){
			tmp[i]=tmp3[1][i];
			vt.push_back(tmp[i]);
		}
		vt.push_back(0);
		sort(vt.begin(),vt.end());
		vt.erase(unique(vt.begin(),vt.end()),vt.end());
		for(int i=0;i<w;i++){
			tmp[i]=lower_bound(vt.begin(),vt.end(),tmp[i])-vt.begin();
		}
	}
	
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r)|flag_p;
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=max(dp[r+1][index][flag],dp[r][index_p][flag_p]+cost_i-cost_r);
	/*
	printf("r=%d %d %d-> %d %d %d\n",r,index_p,flag_p,index,flag,dp[r][index_p][flag_p]+cost_i-cost_r);
	for(int i=0;i<2;i++){
		for(int j=0;j<w;j++){
			printf("%d ",tmp2[i][j]);
		}
		printf("\n");	
	}
	*/
}

bool is_ok(int v){
	while(v>0){
		if(v%4>=2)return false;
		v/=4;
	}
	return true;
}

int main(void){
	scanf("%d%d%d%d",&h,&w,&n,&R);
	init();
	for(int i=0;i<h;i++){
		string s;
		cin >> s;
		for(int j=0;j<w;j++){
			if(s[j]>='0' && s[j]<='9'){
				fie[i][j]=(s[j]-'0')+1;
			}
			if(s[j]>='a' && s[j]<='z'){
				fie[i][j]=(s[j]-'a')+11;
			}
			if(s[j]>='A' && s[j]<='Z'){
				fie[i][j]=(s[j]-'A')+37;
			}
			if(s[j]=='@'){
				sx=j;
				sy=i;
			}
			if(s[j]=='#'){
				fie[i][j]=-1;
			}
			if(s[j]=='*'){
				fie[i][j]=-2;
			}
		}
	}
	for(int i=0;i<n;i++){
		char c;
		int a;
		scanf(" %c%d",&c,&a);
		if(c>='0' && c<='9'){
			val[(c-'0')+1]=a;
		}
		if(c>='a' && c<='z'){
			val[(c-'a')+11]=a;
		}
		if(c>='A' && c<='Z'){
			val[(c-'A')+37]=a;
		}
	}
	for(int i=0;i<=h;i++){
		for(int j=0;j<vec.size();j++){
			for(int k=0;k<2;k++){
				dp[i][j][k]=-INF;
			}
		}
	}
	for(int i=0;i<(1<<w);i++){
		calc_row0(0,i);
	}
	for(int i=1;i<h;i++){
		for(int j=0;j<vec.size();j++){
			for(int k=0;k<2;k++){
				for(int l=0;l<(1<<w);l++){
					calc(i,j,k,l);
				}
			}
		}
	}
	int ans=0;
	for(int i=0;i<vec.size();i++){
		if(is_ok(vec[i])){
			ans=max(ans,dp[h][i][1]);
		}
	}
	printf("%d\n",ans);
	return 0;
}
accuracy: 0.1794871794871795
time_ms: 30
memory_kb: 134468
final_rank: 8

code_snippet: #include <bits/stdc++.h>
#define INF 1000000007
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int h,w,n,R;
vector<int> vec;

int tmp[8];
int ki[8];
int id[1<<25];

void dfs(int x,int c){
	if(x==w){
		int val=0;
		for(int i=0;i<w;i++){
			val+=tmp[i]*ki[i];
		}
		vec.push_back(val);
	}else{
		if(x==0){
			tmp[0]=0;
			dfs(x+1,0);
			tmp[0]=1;
			dfs(x+1,1);
		}else{
			if(tmp[x-1]==0){
				tmp[x]=c+1;
				dfs(x+1,c+1);
				tmp[x]=c;
				dfs(x+1,c);
				tmp[x]=0;
				dfs(x+1,c);
			}else{
				tmp[x]=c;
				dfs(x+1,c);
				tmp[x]=0;
				dfs(x+1,c);
			}
		}
	}
}

int dp[10][100000][2];

void init(){
	ki[0]=1;
	for(int i=1;i<w;i++){
		ki[i]=ki[i-1]*4;
	}
	dfs(0,0);
	sort(vec.begin(),vec.end());
	memset(id,-1,sizeof(id));
	for(int i=0;i<vec.size();i++){
		id[vec[i]]=i;
	}
}

int fie[8][8];
int val[64];
int sx,sy;

int is_person(int r){
	if(sy!=r)return 0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && sx==i)return 1;
	}
	return 0;
}

int calc_rock(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]==-1)return -1;
		if(tmp[i]>=1 && fie[r][i]==-2)sum+=R;
	}
	return sum;
}

int calc_item(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]>=1){
			sum+=val[fie[r][i]];
		}
	}
	return sum;
}

int calc_id(){
	int val=0;
	for(int i=0;i<w;i++){
		val+=tmp[i]*ki[i];
	}
	assert(id[val]!=-1);
	return id[val];
}

void calc_row0(int r,int bit){
	int sz=0;
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			if(i==0){
				sz++;
				tmp[i]=sz;
			}else{
				if(tmp[i-1]!=0){
					tmp[i]=tmp[i-1];
				}else{
					sz++;
					tmp[i]=sz;
				}
			}
		}else{
			tmp[i]=0;
		}
	}
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r);
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[1][index][flag]=cost_i-cost_r;
}

int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
bool fl1[5];
bool fl2[5];
int tmp2[2][8];
int tmp3[2][8];

void dfs_row(int x,int y,int sz){
	tmp3[y][x]=sz;
	if(y==0){
		fl2[tmp2[y][x]]=true;
	}
	for(int i=0;i<4;i++){
		int nx=x+dx[i];
		int ny=y+dy[i];
		if(nx>=0 && nx<w && ny>=0 && ny<2){
			if(tmp2[ny][nx]!=0 && tmp3[ny][nx]==0){
				dfs_row(nx,ny,sz);
			}
		}
	}
}

void calc(int r,int index_p,int flag_p,int bit){
	memset(tmp2,0,sizeof(tmp2));
	{
		int v=vec[index_p];
		int x=0;
		while(v>0){
			if(v%4>=1)tmp2[0][x]=v%4;
			else{
				tmp2[0][x]=0;
			}
			v/=4;
			x++;
		}
	}
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			tmp2[1][i]=1;
		}
	}
	
	memset(fl1,false,sizeof(fl1));
	memset(fl2,false,sizeof(fl2));
	memset(tmp3,0,sizeof(tmp3));
	int sz=0;
	for(int i=0;i<w;i++){
		if(tmp2[0][i]!=0 && tmp3[0][i]==0){
			dfs_row(i,0,sz+1);
			sz++;
		}
	}
	{
		for(int i=0;i<w;i++){
			if(tmp2[0][i]>0){
				fl1[tmp2[0][i]]=true;
			}
		}
		int cn=0;
		for(int i=1;i<=4;i++){
			if(fl1[i])cn++;
		}
		if(cn>=2){
			for(int i=1;i<=4;i++){
				if(fl1[i] && !fl2[i])return;
			}
		}
	}
	{
		vector<int> vt;
		for(int i=0;i<w;i++){
			tmp[i]=tmp3[1][i];
			vt.push_back(tmp[i]);
		}
		vt.push_back(0);
		sort(vt.begin(),vt.end());
		vt.erase(unique(vt.begin(),vt.end()),vt.end());
		for(int i=0;i<w;i++){
			tmp[i]=lower_bound(vt.begin(),vt.end(),tmp[i])-vt.begin();
		}
	}
	
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r)|flag_p;
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[r+1][index][flag]=max(dp[r+1][index][flag],dp[r][index_p][flag_p]+cost_i-cost_r);
}

bool is_ok(int v){
	while(v>0){
		if(v%4>=2)return false;
		v/=4;
	}
	return true;
}

int main(void){
	scanf("%d%d%d%d",&h,&w,&n,&R);
	init();
	for(int i=0;i<h;i++){
		string s;
		cin >> s;
		for(int j=0;j<w;j++){
			if(s[j]>='0' && s[j]<='9'){
				fie[i][j]=(s[j]-'0')+1;
			}
			if(s[j]>='a' && s[j]<='z'){
				fie[i][j]=(s[j]-'a')+11;
			}
			if(s[j]>='A' && s[j]<='Z'){
				fie[i][j]=(s[j]-'A')+37;
			}
			if(s[j]=='@'){
				sx=j;
				sy=i;
			}
			if(s[j]=='#'){
				fie[i][j]=-1;
			}
			if(s[j]=='*'){
				fie[i][j]=-2;
			}
		}
	}
	for(int i=0;i<n;i++){
		char c;
		int a;
		scanf(" %c%d",&c,&a);
		if(c>='0' && c<='9'){
			val[(c-'0')+1]=a;
		}
		if(c>='a' && c<='z'){
			val[(c-'a')+11]=a;
		}
		if(c>='A' && c<='Z'){
			val[(c-'A')+37]=a;
		}
	}
	for(int i=0;i<=h;i++){
		for(int j=0;j<vec.size();j++){
			for(int k=0;k<2;k++){
				dp[i][j][k]=-INF;
			}
		}
	}
	for(int i=0;i<(1<<w);i++){
		calc_row0(0,i);
	}
	for(int i=1;i<h;i++){
		for(int j=0;j<vec.size();j++){
			for(int k=0;k<2;k++){
				for(int l=0;l<(1<<w);l++){
					calc(i,j,k,l);
				}
			}
		}
	}
	int ans=0;
	for(int i=0;i<vec.size();i++){
		if(is_ok(vec[i])){
			ans=max(ans,dp[h][i][1]);
		}
	}
	printf("%d\n",ans);
	return 0;
}
accuracy: 0.02564102564102564
time_ms: 30
memory_kb: 134436
final_rank: 11

code_snippet: #include <bits/stdc++.h>
#define INF 1000000007
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int h,w,n,R;
vector<int> vec;

int tmp[8];
int ki[8];
int id[1<<25];

void dfs(int x,int c){
	if(x==w){
		int val=0;
		for(int i=0;i<w;i++){
			val+=tmp[i]*ki[i];
		}
		vec.push_back(val);
	}else{
		if(x==0){
			tmp[0]=0;
			dfs(x+1,0);
			tmp[0]=1;
			dfs(x+1,1);
		}else{
			if(tmp[x-1]==0){
				tmp[x]=c+1;
				dfs(x+1,c+1);
				tmp[x]=c;
				dfs(x+1,c);
				tmp[x]=0;
				dfs(x+1,c);
			}else{
				tmp[x]=c;
				dfs(x+1,c);
				tmp[x]=0;
				dfs(x+1,c);
			}
		}
	}
}

int dp[10][100000][2];

void init(){
	ki[0]=1;
	for(int i=1;i<w;i++){
		ki[i]=ki[i-1]*4;
	}
	dfs(0,0);
	sort(vec.begin(),vec.end());
	memset(id,-1,sizeof(id));
	for(int i=0;i<vec.size();i++){
		id[vec[i]]=i;
	}
}

int fie[8][8];
int val[64];
int sx,sy;

int is_person(int r){
	if(sy!=r)return 0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && sx==i)return 1;
	}
	return 0;
}

int calc_rock(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]==-1)return -1;
		if(tmp[i]>=1 && fie[r][i]==-2)sum+=R;
	}
	return sum;
}

int calc_item(int r){
	int sum=0;
	for(int i=0;i<w;i++){
		if(tmp[i]>=1 && fie[r][i]>=1){
			sum+=val[fie[r][i]];
		}
	}
	return sum;
}

int calc_id(){
	int val=0;
	for(int i=0;i<w;i++){
		val+=tmp[i]*ki[i];
	}
	assert(id[val]!=-1);
	return id[val];
}

void calc_row0(int r,int bit){
	int sz=0;
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			if(i==0){
				sz++;
				tmp[i]=sz;
			}else{
				if(tmp[i-1]!=0){
					tmp[i]=tmp[i-1];
				}else{
					sz++;
					tmp[i]=sz;
				}
			}
		}else{
			tmp[i]=0;
		}
	}
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r);
	int cost_i=calc_item(r);
	int index=calc_id();
	dp[1][index][flag]=cost_i-cost_r;
	/*
	for(int i=0;i<w;i++){
		printf("%d ",tmp[i]);
	}
	printf("\n");
	printf("%d %d %d %d\n",1,index,flag,cost_i-cost_r);
	*/
}

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

int tmp2[2][8];
int tmp3[2][8];

void dfs_row(int x,int y,int sz){
	tmp3[y][x]=sz;
	for(int i=0;i<4;i++){
		int nx=x+dx[i];
		int ny=y+dy[i];
		if(nx>=0 && nx<w && ny>=0 && ny<2){
			if(tmp2[ny][nx]!=0 && tmp3[ny][nx]==0){
				dfs_row(nx,ny,sz);
			}
		}
	}
}

void calc(int r,int index_p,int flag_p,int bit){
	memset(tmp2,0,sizeof(tmp2));
	{
		int v=vec[index_p];
		int x=0;
		while(v>0){
			if(v%4>=1)tmp2[0][x]=v%4;
			else{
				tmp2[0][x]=0;
			}
			v/=4;
			x++;
		}
	}
	for(int i=0;i<w;i++){
		if((bit>>i)&1){
			tmp2[1][i]=1;
		}
	}
	{
		bool fl1[5];
		bool fl2[5];
		memset(fl1,false,sizeof(fl1));
		memset(fl2,false,sizeof(fl2));
		for(int i=0;i<w;i++){
			if(tmp2[0][i]>0){
				fl1[tmp2[0][i]]=true;
				if(tmp2[1][i]>0){
					fl2[tmp2[0][i]]=true;
				}
			}
		}
		int cn=0;
		for(int i=1;i<=4;i++){
			if(fl1[i])cn++;
		}
		if(cn>=2){
			for(int i=1;i<=4;i++){
				if(fl1[i] && !fl2[i])return;
			}
		}
	}
	memset(tmp3,0,sizeof(tmp3));
	int sz=0;
	for(int i=0;i<w;i++){
		if(tmp2[0][i]!=0 && tmp3[0][i]==0){
			dfs_row(i,0,sz+1);
			sz++;
		}
	}
	/*
	for(int i=0;i<w;i++){
		printf("%d ",tmp3[1][i]);
	}
	printf("\n");
	*/
	{
		vector<int> vt;
		for(int i=0;i<w;i++){
			tmp[i]=tmp3[1][i];
			vt.push_back(tmp[i]);
		}
		vt.push_back(0);
		sort(vt.begin(),vt.end());
		vt.erase(unique(vt.begin(),vt.end()),vt.end());
		for(int i=0;i<w;i++){
			tmp[i]=lower_bound(vt.begin(),vt.end(),tmp[i])-vt.begin();
		}
	}
	
	int cost_r=calc_rock(r);
	if(cost_r==-1)return;
	int flag=is_person(r)|flag_p;
	int cost_i=calc_item(r);
	int index=calc_id();
	/*
	for(int i=0;i<w;i++){
		printf("%d ",tmp[i]);
	}
	printf("\n");
	*/
	dp[r+1][index][flag]=max(dp[r+1][index][flag],dp[r][index_p][flag_p]+cost_i-cost_r);
	//printf("%d %d %d-> %d %d %d\n",r,index_p,flag_p,index,flag,dp[r][index_p][flag_p]+cost_i-cost_r);
}

bool is_ok(int v){
	while(v>0){
		if(v%4>=2)return false;
		v/=4;
	}
	return true;
}

int main(void){
	scanf("%d%d%d%d",&h,&w,&n,&R);
	init();
	for(int i=0;i<h;i++){
		string s;
		cin >> s;
		for(int j=0;j<w;j++){
			if(s[j]>='0' && s[j]<='9'){
				fie[i][j]=(s[j]-'0')+1;
			}
			if(s[j]>='a' && s[j]<='z'){
				fie[i][j]=(s[j]-'a')+11;
			}
			if(s[j]>='A' && s[j]<='Z'){
				fie[i][j]=(s[j]-'A')+37;
			}
			if(s[j]=='@'){
				sx=j;
				sy=i;
			}
			if(s[j]=='#'){
				fie[i][j]=-1;
			}
			if(s[j]=='*'){
				fie[i][j]=-2;
			}
		}
	}
	for(int i=0;i<n;i++){
		char c;
		int a;
		scanf(" %c%d",&c,&a);
		if(c>='0' && c<='9'){
			val[(c-'0')+1]=a;
		}
		if(c>='a' && c<='z'){
			val[(c-'a')+11]=a;
		}
		if(c>='A' && c<='Z'){
			val[(c-'A')+37]=a;
		}
	}
	for(int i=0;i<=h;i++){
		for(int j=0;j<vec.size();j++){
			for(int k=0;k<2;k++){
				dp[i][j][k]=-INF;
			}
		}
	}
	for(int i=0;i<(1<<w);i++){
		calc_row0(0,i);
	}
	for(int i=1;i<h;i++){
		for(int j=0;j<vec.size();j++){
			for(int k=0;k<2;k++){
				for(int l=0;l<(1<<w);l++){
					calc(i,j,k,l);
				}
			}
		}
	}
	int ans=0;
	for(int i=0;i<vec.size();i++){
		if(is_ok(vec[i])){
			ans=max(ans,dp[h][i][1]);
		}
	}
	printf("%d\n",ans);
	return 0;
}
accuracy: 0.1794871794871795
time_ms: 30
memory_kb: 134456
final_rank: 7