zoukankan      html  css  js  c++  java
  • 乘法游戏

    20min写完,没过样例,然后发现循环边界弄错了/kk

    区间 dp 。

    设 f[i][j] 表示从 i 到 j 这个区间取走除两端外所有牌后的最小答案。

    对于从 i 到 j 的区间,我们可以枚举一个分解点 k ,则答案由 f[i][k] 和 f[k][j] 转移而来。即我们可以先取走 i 到 k 之间的牌,再取走 k 到 j 之间的牌,最后取走 k ,就只剩下了 i 和 j 两张牌。

    所以状态转移方程即为 f[i][j] = min(f[i][j],f[i][k]+f[k][j]+a[i]*a[k]*a[j]) 。

    因为要保证 f[i][k] 和 f[k][j] 在 f[i][j] 被求之前就已经求过,所以循环的时候要先枚举长度 l ,在枚举左端点 i ,求出 j = i + l - 1。

    注意不要把循环边界写错了,左端点要枚举到 n - l + 1 。

    #include<bits/stdc++.h>
    using namespace std;
    int f[101][101],n,a[101];
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                f[i][j]=2e9;//因为要求最小值,所以必须赋初始值
            }
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            f[i][i+1]=0;//显然当区间为连续的两张牌时代价为0
        }
        for(int l=3;l<=n;l++)//枚举长度
        {
            for(int i=1;i<=n-l+1;i++)//枚举左端点
            {
                int j=i+l-1;//求出右端点
                for(int k=i+1;k<j;k++)//枚举分界点
                {
                    f[i][j]=min(f[i][j],f[i][k]+f[k][j]+a[i]*a[k]*a[j]);
                }
            }
        }
        cout<<f[1][n]<<endl;
        return 0;
    }
  • 相关阅读:
    设置WebSphere字符集参数
    防SQL注入
    改变radio/checkbox默认样式
    数据完整性约束错误
    Java项目多数据源配置
    No row with the given identifier exists:错误另解
    ICTCLAS20160405分词系统调试过程
    centos7 忘记root密码
    java之Junit
    javaweb之登录
  • 原文地址:https://www.cnblogs.com/ying-xue/p/cheng-fa-you-xi.html
Copyright © 2011-2022 走看看