题意:
DP经典题, 矩阵连乘,求最小运算次数,输出运算优先级(用括号给出)。
思路:
不难定义出状态,dp[i][j] = min(dp[i][k]+dp[k+1][j]+乘法费用);
可以看出大区间确定的前提是小区间已经算出, 所以必须从小到大枚举区间长度,在枚举起点, 便可以确定 终点,在枚举一下过程即可。
一边dp,一边记录下过程。
#include<iostream>
#include<algorithm>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int maxn = 5e4 +10;
struct node
{
int l, r;
}a[15];
int dp[15][15];
int path[15][15];
void printpath(int s, int len)
{
if(len == 1)
{
cout << "A" << s;
return;
}
cout << "(";
int x = path[s][len];
printpath(s,x );
cout << " x ";
printpath(s+x, len-x);
cout << ")";
}
int main()
{
int n;
int Case = 0;
while( scanf("%d", &n)!=EOF)
{
if(n==0)
break;
for(int i = 1; i <= n; i++)
{
scanf("%d %d", &a[i].l, &a[i].r);
}
for(int len = 2; len <= n; len++)
{
for(int s = 1 ; s+len-1 <= n; s++)
{
dp[s][len] = 1e9;
for(int k = 1; k <= len-1; k++)
{
int temp = dp[s][k] + dp[s+k][len-k] + a[s].l*a[s+k].l*a[s+len-1].r;
if(temp < dp[s][len])
{
dp[s][len] = temp;
path[s][len] = k;
}
}
}
}
printf("Case %d: ",++Case);
printpath(1 , n);
cout<<endl;
}
}