codeforces 313D Ilya and Roads (区间dp)

来源:互联网 发布:上海银行淘宝金卡 编辑:程序博客网 时间:2024/06/06 01:41

题意:

n个洞,m个公司,至少补k个洞,每个公司只能补Li到Ri之间的懂,并且费用是ci。问补至少k个洞的最小费用。

题解:

首先我么要这题要知道任意段区间之间的费用是多少,因为公司的区间是可以重合的,但是重合部分要多计算,那么我们可以用(n^3)的计算出任意段区间的费用。

接着我们就可以dp了,dp[i][j]表示前i个点补了k个洞的最小费用。状态方程和往常非常不同本来是要O(n^4)现在优化了一个地方O(n^3)

dp[i][j] = max{ dp[i-1][j] (表示不补i这个洞), dp[i-k][j-k] + cost[i-k+1][i] } 

注意别爆int


#include<iostream>#include<math.h>#include<stdio.h>#include<algorithm>#include<string.h>#include<vector>#include<map>using namespace std;typedef long long lld;const int oo=0x3f3f3f3f;const lld OO=1LL<<61;const int MOD=1000000007;#define maxn 305lld dp[maxn][maxn];lld cost[maxn][maxn];/**dp[i][j] = max{ dp[i-1][j] , dp[i-k][j-k] + cost[i-k+1][i] }*/int main(){    int n,m,k,l,r,c;    while(scanf("%d %d %d",&n,&m,&k)!=EOF)    {        for(int i=0;i<maxn;i++)            for(int j=0;j<maxn;j++)                dp[i][j]=cost[i][j]=OO;        for(int k=1;k<=m;k++)        {            scanf("%d %d %d",&l,&r,&c);            for(int i=l;i<=r;i++)                for(int j=i;j<=r;j++)                    cost[i][j]=min(cost[i][j],(lld)c);        }        dp[0][0]=0;        for(int i=1;i<=n;i++)        {            for(int j=0;j<=n;j++)            {                dp[i][j]=dp[i-1][j];                for(int k=1;k<=i&&k<=j;k++)                {                    dp[i][j]=min(dp[i][j],dp[i-k][j-k]+cost[i-k+1][i]);                }            }        }        if(dp[n][k]==OO)dp[n][k]=-1;        printf("%I64d\n",dp[n][k]);    }    return 0;}/**10 4 67 9 116 9 137 7 73 5 610 7 13 4 158 9 85 6 89 10 61 4 21 4 108 10 1310 1 95 10 14*/




0 0
原创粉丝点击