#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <limits>
using namespace std;
const int MAX_N = 40;
int N;
char slots[MAX_N][MAX_N];
int occupied[MAX_N][MAX_N];
int row_limits[MAX_N][MAX_N]; // 行限制条件的列索引
int row_limit_counts[MAX_N]; // 行限制条件的列数量
double s[MAX_N];
double t[MAX_N];
int col_occupied[MAX_N]; // 每列已经被占据的组件数量
// 检查第 i 行放置 j 个组件是否满足限制条件
bool check_row_limit(int i, int j) {
int sum = 0;
for (int k = 0; k < row_limit_counts[i]; ++k) {
sum += occupied[i][row_limits[i][k] - 1];
}
return (double)j <= sum && (double)j <= N * s[i];
}
// 检查第 j 列放置 k 个组件是否满足限制条件
bool check_col_limit(int j, int k) {
int sum = 0;
for (int i = 0; i < N; ++i) {
sum += occupied[i][j];
}
return (double)k <= sum && (double)k <= N * t[j];
}
int main() {
// 读取输入
cin >> N;
for (int i = 0; i < N; ++i) {
cin >> slots[i];
for (int j = 0; j < N; ++j) {
occupied[i][j] = (slots[i][j] == 'C') ? 1 : 0;
col_occupied[j] += occupied[i][j]; // 统计每列已经被占据的组件数量
}
}
// 读取行限制条件
for (int i = 0; i < N; ++i) {
cin >> row_limit_counts[i];
row_limits[i][0] = row_limit_counts[i];
for (int j = 1; j <= row_limit_counts[i]; ++j) {
cin >> row_limits[i][j];
row_limits[i][j]--; // 转换为从0开始的索引
}
}
// 读取 s 数组
for (int i = 0; i < N; ++i) {
cin >> s[i];
}
// 读取 t 数组
for (int i = 0; i < N; ++i) {
cin >> t[i];
}
// 初始化动态规划数组
vector<vector<int>> dp(N, vector<int>(N * N + 1, 0));
dp[0][0] = 1; // 第一行不放组件是可行的
// 动态规划求解
for (int i = 0; i < N; ++i) {
for (int j = 0; j <= N * N; ++j) {
if (dp[i][j]) {
for (int k = 0; k <= N; ++k) {
if (j + k <= N * N && check_row_limit(i, k) && check_col_limit(i, k)) {
dp[i + 1][j + k] = 1;
}
}
}
}
}
// 计算最多可以放置的组件数量
int max_components = 0;
for (int j = 0; j <= N * N; ++j) {
if (dp[N - 1][j]) {
max_components = j;
}
}
// 输出结果
if (max_components == 0) {
cout << "impossible" << endl;
} else {
cout << max_components << endl;
}
return 0;
}