zoukankan      html  css  js  c++  java
  • 【区间DP&&记忆化搜索】乘法游戏

    题目描述

     乘法游戏是在一行牌上进行的。每一张牌包括了一个正整数。在每一个移动中,玩家拿出一张牌,得分是用它的数字乘以它左边和右边的数,所以不允许拿第1张和最后1张牌。最后一次移动后,这里只剩下两张牌。

        你的目标是使得分的和最小。
        例如,如果数是10 1 50 20 5,依次拿1、20、50,总分是                       10*1*50+50*20*5+10*50*5=8000
        而拿50、20、1,总分是1*50*20+1*20*5+10*1*5=1150。 

    输入

     输入文件mul.in的第一行包括牌数(3<=n<=100),第二行包括N个1-100的整数,用空格分开。

    输出

     输出文件mul.out只有一个数字:最小得分

    样例输入

    6
    10 1 50 50 20 5
    

    样例输出

    3650

    思路

    记忆化搜索和DP本质是一样的,本题相当于用到了分治的思想,都是由小区间合并成大区间,dp[i][j]表示区间i,j之间的最大值,每次枚举[i,j]之间的断点更新dp[i][j]

    值得注意的是初始化的值(-1,0,INF),具体可以看代码qwq

    代码

    (1) 记忆化搜索

    //#include<bits/stdc++.h>
    #include<stdio.h>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N = 105,INF=0x3f3f3f3f; 
    /*
    6 
    10 1 50 50 20 5
    */
    int n,a[N];
    int dp[N][N];
    int dfs(int l,int r)
    {
        if(r<=l+1) return 0;//!
        if(dp[l][r]!=-1)  return dp[l][r];
        dp[l][r]=INF;
        for(int i=l+1;i<=r-1;i++)
        {
            dp[l][r]=min(dp[l][r],dfs(l,i)+dfs(i,r)+a[i]*a[l]*a[r]);
            //    dp[l][r]=min(dp[l][r],dp[l][i]+dp[i][r]+a[i]*a[l]*a[r]);
        }
    //    printf("%d\n",dp[l][r]);
        return dp[l][r];
        
    }
    int main()
    {
        scanf("%d",&n);
        memset(dp,-1,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        dfs(1,n);
        printf("%d",dp[1][n]);
        return 0;
    }

    (2)区间DP的三重循环

    //#include<bits/stdc++.h>
    #include<stdio.h>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N = 105,INF=0x3f3f3f3f; 
    /*
    6 
    10 1 50 50 20 5
    */
    int n,a[N];
    int dp[N][N];
    int main()
    {
        scanf("%d",&n);
        memset(dp,0x3f,sizeof(dp));
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]),dp[i][i+1]=0;
        for(int i=3;i<=n;i++)
        {
            for(int l=1;l+i-1<=n;l++)
            {
                int r=l+i-1;
                dp[l][r]=INF;
                for(int k=l+1;k<=r-1;k++)
                {
                    dp[l][r]=min(dp[l][r],dp[l][k]+dp[k][r]+a[l]*a[r]*a[k]);
                }
            }    
        }
        printf("%d",dp[1][n]);
        return 0;
    }
  • 相关阅读:
    cpu 怎么区分指令与数据,寄存器与内存各自对应什么
    添加省略号
    有关自有属性,原型属性的问题
    实现一个new
    滚动条样式修改
    备忘录实现+具体需求应用备忘录
    Math.random生成指定范围的随机数
    reduce详细用法
    一个搜索上下的功能,用的不多
    svg拖拽rect,line,circle
  • 原文地址:https://www.cnblogs.com/conprour/p/14520270.html
Copyright © 2011-2022 走看看