AHU-727 美妙音乐 【DP】
Description
西瓜和Roll组团去冒险,他们打开了隐藏的密门,发现了矮人矿洞的秘密。那是多年前由矮人王亲自下令改建的密室,据说只有最美妙的音乐可以指引他们找到宝藏。
一首音乐是最美妙的,当且仅当每两个相邻音符的和谐度之和最大。西瓜发现了一张矮人公认的最美和谐度表harmony。西瓜发现,他可以使用m种音符构造音乐,最终构成的音乐共包含n个音符。西瓜兴致勃勃地谱出了最美妙的音乐,不幸的是,在矮人矿洞Roll发现矮人们的音乐有固定的模板,他们应当按照矮人们的模板再谱出一首曲子。由于西瓜的谱曲天赋有限,一天只能谱写一首曲子,他们想尽快进入那个矿洞,只有找你来帮助他们。
Input
输入数据第一行,包含一个整数T,为数据组数(1≤T≤10)。
对于每组数据,第一行包含两个整数n和m,(1≤n≤100,1≤m≤50)。
接下来m行,每行包括m个用空格隔开的整数,第i行第j列表示harmony(i,j)(0≤harmony(i,j) ≤100)。
接下来一行包含n个用空格隔开的整数ai(-1≤ai≤m且ai≠0),ai为-1时代表你可以随意指定音符,ai>0时你不能改变音符。
Output
对于每组数据,输出包括两个用空格隔开的整数x,y。x为在矮人模板下最大的和谐度,y为没有模板限制时最大的和谐度。
Sample Input
1 42 2 31 96 18 96 2 -1 -1 2 -1 -1 -1 -1 2 -1 -1 1 -1 1 -1 -1 -1 2 1 -1 -1 -1 -1 1 2 2 -1 -1 1 2 2 -1 1 2 -1 2 -1 2 1 2 -1 -1
Sample Output
3390 3936
思路:
比较容易想到是一道DP,用f(i,j)代表到第i个音符时选择音符j的最大和谐度,k代表第i-1个音符,则不按模板时,有转移方程:
f(i,j) = max1<=k<=m(f(i,j), f(i-1,k)+h(k,j))
按照模板时,只要ai>0时将j!=ai时的f(i,j)全部赋值为-inf再按上式递推就行
Code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define INF 0x3f3f3f3f 4 int f[105][55], g[105][55], h[55][55], a[105]; 5 6 int main() { 7 ios::sync_with_stdio(false); 8 int T, n, m; 9 cin >> T; 10 while (T--) { 11 memset(f, 0, sizeof(f)); 12 memset(g, 0, sizeof(g)); 13 cin >> n >> m; 14 for (int i = 1; i <= m; ++i) 15 for (int j = 1; j <= m; ++j) 16 cin >> h[i][j]; 17 for (int i = 1; i <= n; ++i) cin >> a[i]; 18 int ans1 = 0, ans2 = 0; 19 for (int i = 2; i <= n; ++i) 20 for (int j = 1; j <= m; ++j) 21 for (int k = 1; k <= m; ++k) { 22 f[i][j] = max(f[i][j], f[i-1][k] + h[k][j]); 23 ans2 = max(ans2, f[i][j]); 24 } 25 if (a[1] > 0) 26 for (int i = 1; i <= m; ++i) 27 if (a[1] != i) g[1][i] = -INF; 28 for (int i = 2; i <= n; ++i) { 29 if (a[i] > 0) { 30 for (int j = 1; j <= m; ++j) 31 if (j != a[i]) g[i][j] = -INF; 32 else for (int k = 1; k <= m; ++k) 33 g[i][j] = max(g[i][j], g[i-1][k] + h[k][j]); 34 } 35 else { 36 for (int j = 1; j <= m; ++j) 37 for (int k = 1; k <= m; ++k) 38 g[i][j] = max(g[i][j], g[i-1][k] + h[k][j]); 39 } 40 } 41 for (int i = 1; i <= m; ++i) ans1 = max(ans1, g[n][i]); 42 cout << ans1 << " " << ans2 << endl; 43 } 44 45 return 0; 46 }