zoukankan      html  css  js  c++  java
  • HDU

    题目链接 : HDU - 2829

    题意 :

    给出一条笔直无分叉的铁路上有n个仓库,每个仓库有一个v[i]代表价值;

    每两个仓库之间算作一段铁路,现在有m次攻击机会,一次攻击可以炸毁一段铁路;

    m次攻击后,剩余的总价值为:Σ(v[i]*v[j]),i和j为所有任意两个互相可到达的仓库。

    现要求选定m段铁路进行攻击炸毁,然后使得总价值最小。

    思路 :

    正常的思路,首先想到用滚动数组,用dp[i][j] 代表 以 j 结尾的分成了 i 段的最小值,那

    dp[i][j]=mindp[i−1][k]+w[j]−w[k]−sum[k]∗(sum[j]−sum[k])dp[i][j] = min { dp[i-1][k] + w[j] - w[k] - sum[k] * (sum[j] - sum[k]) } dp[i][j]=mindp[i1][k]+w[j]w[k]sum[k](sum[j]sum[k])但是对于这种情况 ,

    我们要 遍历一遍 i j k 因此时间复杂度是O( n ^ 3 ) 而题目的数据是1000,因此要用的斜

    率优化,如果对于 q 来说 有一个更加优化的 k 的话那么

    dp[i−1][k]+w[j]−w[k]−sum[k]∗(sum[j]−sum[k])&lt;dp[i−1][q]+w[j]−w[q]−sum[q]∗(sum[j]−sum[q])dp[i-1][k] + w[j] - w[k] - sum[k] * (sum[j] - sum[k]) &lt; dp[i-1][q] + w[j] - w[q] - sum[q] * (sum[j] - sum[q])dp[i1][k]+w[j]w[k]sum[k](sum[j]sum[k])<dp[i1][q]+w[j]w[q]sum[q](sum[j]sum[q])

    化简得 :

    (dp[i−1][k]−w[k]+sum[k]∗sum[k]−(dp[i−1][q]−w[q]+sum[q]∗sum[q]))/(sum[k)−sum[q])&lt;sum[j](dp[i-1][k] - w[k] + sum[k] * sum[k] - ( dp[i-1][q] - w[q] + sum[q] * sum[q] )) / (sum[k) - sum[q]) &lt; sum[j](dp[i1][k]w[k]+sum[k]sum[k](dp[i1][q]w[q]+sum[q]sum[q]))/(sum[k)sum[q])<sum[j]

    AC code:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    const int maxn = 1e3+50;
    
    ll dp[maxn][maxn] ,w[maxn] ,sum[maxn] ,v[maxn] ;
    int que[maxn] ,head ,tail ;
    int n ,m ;
    
    ll y (int i,int j,int k) {
    	return dp[i][k] - w[k] + sum[k] * sum[k] - (dp[i][j] - w[j] + sum[j] * sum[j]);
    }
    
    ll x (int j,int k) {
    	return sum[k] - sum[j];
    }
    
    int main() {
    	while(~scanf("%d %d",&n ,&m ) &&(n+m)) {
    		w[0] = sum[0] = 0;
    		for (int i = 1;i<=n;i++) {
    			scanf("%lld",&v[i]);
    			sum[i] = sum[i-1] + v[i];
    			w[i] = w[i-1] + sum[i-1] * v[i];
    		}
    		for (int i = 1;i <= n;i++) {
    			dp[1][i] = w[i];
    		}
    		for (int i = 2;i <= m+1;i++) {
    			head = tail = 0;
    			que[tail ++] = i-1;
    			for (int j = i;j<=n;j++) {
    				while(head + 1 < tail && y(i-1 ,que[head] ,que[head + 1]) < x(que[head] ,que[head + 1]) * sum[j] ) head ++;
    				dp[i][j] = dp[i-1][que[head]] + w[j] - w[que[head]] - sum[que[head]] * ( sum[j] - sum[que[head]] ); 
    				while(head + 1 < tail && y(i-1 ,que[tail-2] ,que[tail-1]) * x(que[tail-1] ,j ) >= y(i-1 ,que[tail - 1] ,j) * x(que[tail-2] ,que[tail-1]) ) tail -- ;
    				que[tail ++] = j;
    			}
    		}
    		printf("%lld
    ",dp[m+1][n]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    jq ajax注册检查用户名
    jq ajax页面交互
    Digit Counting UVA – 1225
    Molar mass UVA – 1586
    P1571 眼红的Medusa
    A. Digits Sequence Dividing
    Codeforces Round #535 (Div. 3) a题
    Digit Generator UVA – 1583
    Good Bye 2018 B
    电梯 HDU – 1008
  • 原文地址:https://www.cnblogs.com/Nlifea/p/11745942.html
Copyright © 2011-2022 走看看