zoukankan      html  css  js  c++  java
  • 【Comet OJ

    题目大意:

    题目链接:https://www.cometoj.com/contest/58/problem/C?problem_id=2760
    nn个物品,每个物品有a,ba,b两个属性,每次合并两个相邻的物品i,i+1i,i+1会合并成一个(ai,bi+1)(a_i,b_{i+1})物品,但需花费代价ai+1×bia_{i+1} imes b_i。在开始前可以选择一段区间里的物品,然他们的两个属性全部乘kk。求合并后代价的最小值。


    思路:

    先考虑没有乘kk的操作,那么显然无论合并的顺序是怎样的,最终结果都相同。因为任意一次合并都没有拆散其它相邻的物品。
    所以只需考虑乘kk的操作使得答案更小。那么设f[i][0/1/2]f[i][0/1/2]表示全部不使用乘kk的代价、第ii个物品一定使用乘kk的最小代价、前i1i-1个物品使用了乘kk,第ii个物品不使用乘kk的最小代价。
    c[i]c[i]为本次代价,那么转移方程显然
    f[i][0]=f[i1][0]+c[i]f[i][0]=f[i-1][0]+c[i]
    f[i][1]=min(f[i1][0]+c[i]×k,f[i1][1]+c[i]×k×k)f[i][1]=min(f[i-1][0]+c[i] imes k,f[i-1][1]+c[i] imes k imes k)
    f[i][2]=min(f[i1][2]+c[i],f[i1][1]+c[i]×k)f[i][2]=min(f[i-1][2]+c[i],f[i-1][1]+c[i] imes k)

    最后取个minmin即可。


    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    const int N=100010;
    int n;
    ll f[N][3],a[N],b[N],c[N],k;
    
    int main()
    {
    	scanf("%d",&n);
    	scanf("%lld",&k);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%lld%lld",&a[i],&b[i]);
    		if (i>=2) c[i-1]=a[i]*b[i-1];
    	}
    	memset(f,0x3f3f3f3f,sizeof(f));
    	f[0][0]=f[0][1]=f[0][2]=0;
    	for (int i=1;i<n;i++)
    	{
    		f[i][0]=f[i-1][0]+c[i];
    		f[i][1]=min(f[i-1][0]+c[i]*k,f[i-1][1]+c[i]*k*k);
    		f[i][2]=min(f[i-1][2]+c[i],f[i-1][1]+c[i]*k);
    	}
    	printf("%lld
    ",min(f[n-1][0],min(f[n-1][1],f[n-1][2])));
    	return 0;
    }
    
  • 相关阅读:
    开开心心
    HOW HE/SHE'S SEEN
    天池
    sql server deadlock跟踪的四种方法
    reduce 好东西
    object方法
    页面横向滚动 联动 进度条
    浅拷贝、深拷贝
    图片下载
    axios简单封装
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998064.html
Copyright © 2011-2022 走看看