SPOJ 345 - Mixtures 区间动态规划

有n个混合物排成一排,每个混合物有一个颜色值0<=color<=99,

规定合并只能合并相邻两个,

将颜色a的混合物与颜色b的混合物合并后,颜色为( a+b ) % 100,并产生a*b的污染,

现在要将所有混合物合并,问产生污染的最小值。

【区间动规】很经典的区间动规

dp[i][j] = min { dp[i][k] + dp[k+1][j] + sum[i][k]*sum[k+1][j] }

具体的DP次序详见代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<queue>
#include<string>
#include<sstream>
#define eps 1e-9
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define MAXN 1005
#define MAXM 40005
#define INF 0x3fffffff
using namespace std;
typedef long long LL;
int i,j,k,n,m,x,y,T,ans,big,cas,num,len;
bool flag;
int dp[105][105],sum[105][105],a[105];
int main()
{
    while (~scanf("%d",&n))
    {
        for (i=1;i<=n;i++) scanf("%d",&a[i]);

        for (i=1;i<=n;i++)
        {
            sum[i][i]=a[i];
            for (j=i+1;j<=n;j++)
            {
                sum[i][j]=(sum[i][j-1]+a[j])%100;
            }
        }

        memset(dp,-1,sizeof(dp));
        for (i=1;i<=n;i++) dp[i][i]=0;

        for (i=n;i>=1;i--)//枚举左端点
        {
            for (j=i+1;j<=n;j++)//枚举右端点
            {
                for (k=i;k<=j-1;k++)//枚举中间结点
                {
                    if (dp[i][j]==-1) dp[i][j]=dp[i][k]+dp[k+1][j]+sum[i][k]*sum[k+1][j];
                    else dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[i][k]*sum[k+1][j]);
                }
            }
        }

        printf("%d\n",dp[1][n]);

    }
    return 0;
}
时间: 2024-12-19 12:36:18

SPOJ 345 - Mixtures 区间动态规划的相关文章

[ACM] POJ 1141 Brackets Sequence (区间动态规划)

Brackets Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 25087   Accepted: 7069   Special Judge Description Let us define a regular brackets sequence in the following way: 1. Empty sequence is a regular sequence. 2. If S is a re

区间动态规划-DFS种类数(SOJ 2469)

2469: Exploring Pyramids 问题:给出一棵树我们可以写出它的深搜结果,现在给出深搜结果字符串$S$求解对应树的种类数. 例子:深搜结果:$ABABABA$,对应的树(根结点在底层)有$5$个. 分析:应用区间动态规划,定义$dp[i][j]$为$S[i..j]$对应的树的个数,则分两类: (1)$S[i]$有一个子结点(上例中前两种情况),$S[i..j]$对应的树的个数就等于$S[i+1..j-1]$对应的树的个数,前提是$S[i]=S[j]$.即,若$S[i]=S[j]

【算法?日更?第八期】区间动态规划:1572:括号配对题解

废话不多说,直接上题: 题目测评链接:戳这里 其实什么GBE都没用,小编最开始看了半天不懂,看了看别人的博客才知道这段话没什么用处.其实就是给一段字符串,判断是否括号是配对的. 这道题一看就会想到区间动态规划(不会戳这里临时补一补),最开始先老老实实地写了一遍区间动态规划,后来觉得用栈也可以,于是写了一遍,代码如下: 1 #include<iostream> 2 #include<cstring> 3 #include<stack> 4 using namespace

SPOJ MIXTURES 区间dp

Harry Potter has n mixtures in front of him, arranged in a row. Each mixture has one of 100 different colors (colors have numbers from 0 to 99). He wants to mix all these mixtures together. At each step, he is going to take two mixtures that stand ne

区间动态规划

区间 DP是指在一段区间上进行的一系列动态规划. 对于区间 DP 这一类问题,我们需要计算区间 [1,n] 的答案,通常用一个二维数组 dp 表示,其中 dp[x][y] 表示区间 [x,y]. 有些题目,dp[l][r] 由 dp[l][r?1] 与 dp[l+1][r] 推得:也有些题目,我们需要枚举区间 [l,r] 内的中间点,由两个子问题合并得到,也可以说 dp[l][r] 由 dp[l][k] 与 dp[k+1][r] 推得,其中 l≤k<r. 对于长度为 n 的区间 DP,我们可以先

SPOJ GSS1 静态区间求解最大子段和

题目大意: 给定n个数,再给q个区间询问,希望在区间s,t中找到一段连续的子序列使其和最大 因为询问上万,节点数50000,明显是用线段树去做,这里很明显的区间更新,唯一写起来有点恶心的是询问 每一个区间的最大都要跟左右区间的左最大右最大有关系 反正时要注意细节了,查询的时候同时要查询其左右连续最大 自己的错误在于左右连续最大的更新出问题,这个希望自己以后要注意 1 #include <cstdio> 2 #include <cstring> 3 #include <iost

hdu6249 区间动态规划

题目链接 题意:给出一些区间,求选k个区间能覆盖的最多点的数量 思路:定义dp[i][j]为前i个点取j个区间的最大值.dp[i][j]可以转移到dp[i+1][j+1]和以i+1为起点的区间终点 具体可以看代码 #include <iostream> #include <cstdio> using namespace std; #define ll long long const int maxn = 2005; int t[maxn],dp[maxn][maxn]; int m

poj 1160 Post Office (区间动态规划)

Post Office Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 15966   Accepted: 8671 Description There is a straight highway with villages alongside the highway. The highway is represented as an integer axis, and the position of each villa

动态规划——区间

Wikioi 1048 石子归并 题目描述 Description 有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1].问安排怎样的合并顺序,能够使得总合并代价达到最小. 输入描述 Input Description 第一行一个整数n(n<=100) 第二行n个整数w1,w2...wn  (wi <= 100) 输出描述 Output Description 一个整数表示最小合并代价 样例输入 Sample