• 洛谷 P2365 任务安排_代价提前计算 + 好题


    最开始,笔者将状态 fif_{i}fi 定义为1到i的最小花费 ,我们不难得到这样的一个状态转移方程,即

    fi=(sumti−sumtj+S+Costj)∗(sumfi−sumfj)f_{i}=(sumt_{i}-sumt_{j}+S+Cost_{j})*(sumf_{i}-sumf_{j})fi=(sumtisumtj+S+Costj)(sumfisumfj)

    可是我们发现这时 CostjCost_{j}Costj 非常不好算,而且当前的决策还会对后面的决策产生影响,而且这个转移方程是明显不具备最优子结构的(想一想, 为什么?)。
    那么,我们就换一个思路,将 fif_{i}fi 重新定义,我们可将 fif_{i}fi 定义为

    fi=min(fj+(sumfi−sumfj)∗(sumti−sumtj+S)+(sumti−sumtj+S)∗(sumfn−sumfi))f_{i}=min(f_{j}+(sumf_{i}-sumf_{j})*(sumt_{i}-sumt_{j}+S)+(sumt_{i}-sumt_{j}+S)*(sumf_{n}-sumf_{i}))fi=min(fj+(sumfisumfj)(sumtisumtj+S)+(sumtisumtj+S)(sumfnsumfi))

    即我们定义的 fif_{i}fi 还考虑了对后面的贡献,这样就可以愉快的进行dp了。
    时间复杂度是 O(n2)O(n^2)O(n2) ,其实我们还可以用斜率优化将其优化到 O(n)O(n)O(n) ,不过方法不难,笔者就不再阐述。
    Code:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn = 5002;
    const long long inf = 10000000000 + 3;
    long long sumf[maxn], sumt[maxn], f[maxn];
    int main()
    {
        int n, s;
        scanf("%d%d",&n,&s);
        for(int i = 1;i <= n;++i)
        {
            scanf("%d%d",&sumt[i], &sumf[i]);
            sumt[i] += sumt[i - 1], sumf[i] += sumf[i - 1]; 
        }
        for(int i = 1;i <= n; ++i)
        {
            f[i] = inf;
            for(int j = 0;j < i; ++j)
                f[i] = min(f[i], f[j] + (sumf[i] - sumf[j]) * (sumt[i] - sumt[j] + s) + (sumt[i] - sumt[j] + s) * (sumf[n] - sumf[i]));
        }
        printf("%lld",f[n]);
        return 0;
    }
    

      

  • 相关阅读:
    linux分析、诊断及调优必备的“杀器”之二
    浏览器被“hao123.3377.com”主页劫持的解决办法
    Nginx一个实现负载均衡的强大web server
    【百度之星
    c/c++ 参数传递
    【百度之星】-IP聚合
    百度之星-大搬家-递推
    IOS开发之Swift学习笔记
    【Leetcode】84. Largest Rectangle in Histogram 85. Maximal Rectangle
    【Leetcode】82. Remove Duplicates from Sorted List II
  • 原文地址:https://www.cnblogs.com/guangheli/p/9845155.html
Copyright © 2020-2023  润新知