题目链接:http://codeforces.com/contest/724/problem/E

 

题目大意:

有n个城市,每个城市有pi件商品,最多能出售si件商品,对于任意一队城市i,j,其中i<j,可以从城市i往j运输最多c件商品。 求最多一共能卖出多少件商品。  n<=10000

 

解法一(官方解法):

构造网络流,因为边太多,不可能直接跑最大流。 根据图的特殊性,考虑用dp求解最小割。

状态:dp[i,j]表示前i个中有j个和源点相通的最小割。

转移:如果第i个点不和源点相连,那么pi这条边一定要割掉,并且之前和源点相连的j个点,每个点会有一条边连向第i个点,这些边也要割掉。 花费是dp[i-1][j]+p[i]+j*c;

如果第i个点和源点相连,那么si这条边肯定要割掉。 花费是dp[i-1][j-1]+s[i];

故dp[i][j]=min(dp[i-1][j]+p[i]+j*c,dp[i-1][j-1]+s[i])。

最后答案就是min(dp[n][0...n])  时间复杂度O(n2)

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cstdlib>
#include <set>
using namespace std;

#define X first
#define Y second
#define Mod 1000000007
#define N 10010
#define M 400010
typedef long long ll;
typedef pair<int,int> pii;

int n,c;
int s[N],p[N];
ll dp[2][N];

int main()
{
    //freopen("in.in","r",stdin);
    //freopen("out.out","w",stdout);
    
    scanf("%d%d",&n,&c);
    for (int i=1;i<=n;i++) scanf("%d",&p[i]);
    for (int i=1;i<=n;i++) scanf("%d",&s[i]);
    
    
    int op=0; 
    for (int j=1;j<=n;j++) dp[op][j]=1e18;
    for (int i=1;i<=n;i++)
    {
        op^=1;
        for (int j=0;j<=n;j++)
        {
            if (j) dp[op][j]=min(dp[op^1][j-1]+s[i],dp[op^1][j]+1ll*j*c+p[i]);
            else dp[op][j]=dp[op^1][j]+p[i];
            //cout<<i<<" "<<j<<" "<<dp[op][j]<<endl;
        }
    }
    ll ans=1e18;
    for (int j=0;j<=n;j++) ans=min(ans,dp[op][j]);
    printf("%I64d\n",ans);

    return 0;
}
View Code

相关文章: