题意:给你一个字符串,告诉你两个字符会合成的字符和代价,问最后字符串合成一个字符所需的最下代价。如果合成的两个字符代价一样,那么取较前给出的字符。
f[i][j][k]:i到j这段区间合成k的最小代价
注意最后一个case 不要输出换行。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define VI vector<int>
#define pii pair<int,int>
#define LL long long
#define DB double
using namespace std;
const int MAXN = 210;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double eps = 1e-10;
char c[30],buf[MAXN];;
int id[300],f[MAXN][MAXN][30];
int mat[MAXN][MAXN];
vector<pii > b[30];
int main()
{
bool flag = false;
int n;
while(scanf("%d",&n) && n){
if(!flag) flag = true;
else printf("\n");
for(int i = 0; i < n;i++){
b[i].clear();
char s[10];
scanf("%s",s);
c[i] = s[0];
id[c[i]] = i;
}
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
char goal[2];
int cost;
scanf("%d-%s",&cost,goal);
mat[i][j] = cost;
b[id[goal[0]]].pb(mp(i,j));
}
}
int m;scanf("%d",&m);
for(int q = 0; q < m; q++){
scanf("%s",buf);
int len = strlen(buf);
memset(f,INF,sizeof(f));
for(int k = 0; k < n; k++)
for(int i = 0; i < len;i++)
if(id[buf[i]] == k) f[i][i][k] = 0;
for(int r = 1; r < len; r++)
for(int l = r - 1; l >= 0; l--)
for(int k = 0; k < n;k++)
for(int mid = l;mid < r; mid++)
for(int i = 0; i < (int)b[k].size();i++){
int x = b[k][i].fi;
int y = b[k][i].se;
// cout<<x<<' '<<y<<endl;
f[l][r][k] = min(f[l][mid][x] + f[mid+1][r][y] + mat[x][y],f[l][r][k]);
// cout<<l<<' '<<mid<<' '<<r<<' '<<k<<' '<<f[l][r][k]<<endl;
}
int ans = INF,cid = 0;
for(int k = 0; k < n;k++){
if(f[0][len-1][k] < ans){
ans = f[0][len-1][k];
cid = k;
}
}
printf("%d-%c\n",ans,c[cid]);
}
// printf("\n");
}
return 0;
}