题意 n*m(n,m <= 7 )的图里边最多18个串 每个串长度不超过k (k <= 5),每次选两个消除,类似连连看的方式,但是只能变一次方向,消除两个获得的价值是两个字符串位置一样的个数,假如 一共有 i 个,得到价值就是 s[i] (0 <= i <= k). 问消除所有的获得最大价值。
思路
状压dp,预处理一些东西,加速dp
算了复杂度感觉是 , 但实际可能有剪枝,达不到这个复杂度,莽一发过了。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
char s[10][10][10];
int cnt;
struct node {
int x, y;
}p[25];
int can[25][25][2], dp[N], val[25][25], a[15];
void solve(int j, int k) {
int x1 = p[j].x, x2 = p[k].x; if(x1 > x2) swap(x1, x2);
int y1 = p[j].y, y2 = p[k].y; if(y1 > y2) swap(y1, y2);
int v1 = 0, v2 = 0;
for(int i = 0; i < cnt; i++) {
if(p[i].x == p[j].x && p[i].y >= y1 && p[i].y <= y2)
v1 |= (1 << i);
if(p[i].y == p[k].y && p[i].x >= x1 && p[i].x <= x2)
v1 |= (1 << i);
if(p[i].x == p[k].x && p[i].y >= y1 && p[i].y <= y2)
v2 |= (1 << i);
if(p[i].y == p[j].y && p[i].x >= x1 && p[i].x <= x2)
v2 |= (1 << i);
}
v1 ^= (1 << j) | (1 << k);
v2 ^= (1 << k) | (1 << j);
can[j][k][0] = v1;
can[j][k][1] = v2;
}
int T, n, m, k, all;
int get(int i, int j) {
int num = 0;
for(int h = 0; h < k; h++) {
if(s[p[i].x][p[i].y][h] == s[p[j].x][p[j].y][h]) num++;
}
return num;
}
void init() {
all = (1 << cnt) - 1;
for(int i = 0; i < cnt; i++)
for(int j = i + 1; j < cnt; j++) {
solve(i, j);
val[i][j] = a[get(i, j)];
}
}
int main()
{
//#ifndef ONLINE_JUDGE
// freopen("h.in", "r", stdin);
//#endif
scanf("%d", &T);
while(T--) {
cnt = 0;
scanf("%d %d %d", &n, &m, &k);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
scanf(" %s", s[i][j]);
if(s[i][j][0] != '-') p[cnt++] = {i, j};
}
}
for(int i = 0; i <= k; i++) scanf("%d", &a[i]);
for(int sta = 0; sta < (1 << cnt); sta++) dp[sta] = -1e9;
dp[0] = 0;
init();
for(int sta = 0; sta < (1 << cnt); sta++) {
for(int i = 0; i < cnt; i++) {
if(sta & (1 << i)) continue;
for(int j = i + 1; j < cnt; j++) {
if(sta & (1 << j)) continue;
if((can[i][j][0] & sta) == can[i][j][0] || (can[i][j][1] & sta) == can[i][j][1])
dp[sta | (1 << i) | (1 << j)] = max(dp[sta | (1 << i) | (1 << j)], dp[sta] + val[i][j]);
}
}
}
printf("%d\n", dp[all]);
}
return 0;
}
京公网安备 11010502036488号