• [jdoj1090]矩阵_区间dp


    矩阵 jdoj-1910

        题目大意:给你连续的n个矩阵的长和宽,保证每连续的两个相邻矩阵满足相乘的条件,不能改变题目中矩阵的位置,求将这些矩阵相乘为一个矩阵的最小乘法次数。

        注释:1<=n<=500,a,b<=50.定义矩阵A(x,a)和矩阵B(a,y)的乘法次数为x*a*y.

          想法:这题,不会这种算法tm没个写,我连WA三回结果是算法有问题。下面,我来介绍一种动态规划——区间dp

            所谓区间dp,就是在将区间定义为一个变量,然后进行dp。这么说可能有些空洞,我们直接来看这道题。

            首先,我们设状态dp[i][i+len-1]表示从第i个矩阵开始的len个矩阵相乘为一个矩阵的最小乘法次数。我们考虑如何转移。在这里,必须将len枚举在最外层循环,这样的话我们就可以根据小区间来直接更新大区间。这道题的dp转移方程就是

            dp[i][i+len-1]=min(dp[i][i+len-1] , dp[i][j]+dp[j+1][i+len-1]+a[i].x*a[j].y*a[i+len-1].y)。

            这显然是十分好理解的,就是说我枚举这个长度为len的区间的断点,被断点分开的两段区间的长度一定是小于len的,也就是说这两段区间是我们枚举过的。这道题也就迎刃而解了。

          最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    ll ans[510][510];
    struct Node//每一个矩阵的长和宽
    {
    	int x,y;
    }a[510];
    int main()
    {
    	int n;
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d%d",&a[i].x,&a[i].y);
    	}
    	memset(ans,0x3f,sizeof(ans));
    	for(int i=1;i<=n;i++) ans[i][i]=0;
    	for(int len=2;len<=n;len++)
    	{
    		for(int i=1;i<=n;i++)
    		{
    			if(i+len-1>n) break;//由于我是枚举len,所以必须特判i+len-1的合法性
    			for(int j=i;j<=i+len-2;j++)
    			{
    				ans[i][i+len-1]=min(ans[i][i+len-1],ans[i][j]+ans[j+1][i+len-1]+a[i].x*a[j].y*a[i+len-1].y);//dp转移方程
    			}
    		}
    	}
    	printf("%lld
    ",ans[1][n]);
    	return 0;
    }
    

         小结:背包dp刷完了,开始我的区间dp的魔鬼TwoDays!!

  • 相关阅读:
    CF 980D Perfect Groups(数论)
    CF 983B XOR-pyramid(区间dp,异或)
    CF 984C Finite or not? (数论)
    CF 979D Kuro and GCD and XOR and SUM(异或 Trie)
    (可能)常用打比赛网站
    排序工作量之新任务(SHOI2001)
    【图楼】长期图楼~~不定期更新
    【题解】SHOI2014概率充电器
    【题解】NOIP2015推销员
    [NOI2015][bzoj4197] 寿司晚宴 [状压dp+质因数]
  • 原文地址:https://www.cnblogs.com/ShuraK/p/8519748.html
Copyright © 2020-2023  润新知