题目链接: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[][N]; int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout); scanf("%d%d",&n,&c);
for (int i=;i<=n;i++) scanf("%d",&p[i]);
for (int i=;i<=n;i++) scanf("%d",&s[i]); int op=;
for (int j=;j<=n;j++) dp[op][j]=1e18;
for (int i=;i<=n;i++)
{
op^=;
for (int j=;j<=n;j++)
{
if (j) dp[op][j]=min(dp[op^][j-]+s[i],dp[op^][j]+1ll*j*c+p[i]);
else dp[op][j]=dp[op^][j]+p[i];
//cout<<i<<" "<<j<<" "<<dp[op][j]<<endl;
}
}
ll ans=1e18;
for (int j=;j<=n;j++) ans=min(ans,dp[op][j]);
printf("%I64d\n",ans); return ;
}

解法二:

同样是求最小割。但是利用了贪心的策略。分别求出有i个点和源点相连的 最小割。

假设已经有k-1个点与源点相连,现在要增加第k个点p。

1.对于这k-1个点中编号比p小的,假设有s个,在加入p之前,它们连到p的边肯定已经被割掉了,否则p也与源点相连。 如果加入p,那么这些边就没必要割掉了,从当前代价里减去。

2.对于这k-1个点中编号比p大的,假设有t个,在加入p之后,p连到它们的边是没有必要去割的。

3.对于编号比p大而且不在这k-1个点中的, p连到它们的边必须割去,否则它们也会与源点相连。

根据2,3     需要新割掉n-p-t条边,代价增加(n-p-t)*c;   根据1  代价减少s*c;

总的割边数变化是(n-p-t-s) =  n-p-(s+t) =  n-p-(k-1)= (n-p+1)-k.

把这个代价分为2个部分,一部分是n-p+1, 只和加入的点的编号有关 。一部分是-k,只和目前加入了几个点有关。

因此就可以贪心,每次选择n-p+1最小的点加入。

用一个multiset或者heap来维护最小值,时间复杂度O(nlogn)

代码:

#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 p[N],s[N];
multiset<ll> st; int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout); ll ans,sum=;
scanf("%d%d",&n,&c);
for (int i=;i<=n;i++) scanf("%d",&p[i]),sum+=p[i];
for (int i=;i<=n;i++) scanf("%d",&s[i]),st.insert(s[i]-p[i]+1ll*(n+-i)*c); ans=sum;
for (int i=;i<=n;i++)
{
sum+= *st.begin()-1ll*i*c;
st.erase(st.begin());
ans=min(ans,sum);
}
printf("%I64d\n",ans); return ;
}

Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) E. Goods transportation (非官方贪心解法)的更多相关文章

  1. CF Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined)

    1. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) B. Batch Sort    暴力枚举,水 1.题意:n*m的数组, ...

  2. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined)D Dense Subsequence

    传送门:D Dense Subsequence 题意:输入一个m,然后输入一个字符串,从字符串中取出一些字符组成一个串,要求满足:在任意长度为m的区间内都至少有一个字符被取到,找出所有可能性中字典序最 ...

  3. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) B. Batch Sort

    链接 题意:输入n,m,表示一个n行m列的矩阵,每一行数字都是1-m,顺序可能是乱的,每一行可以交换任意2个数的位置,并且可以交换任意2列的所有数 问是否可以使每一行严格递增 思路:暴力枚举所有可能的 ...

  4. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) C. Ray Tracing

    我不告诉你这个链接是什么 分析:模拟可以过,但是好烦啊..不会写.还有一个扩展欧几里得的方法,见下: 假设光线没有反射,而是对应的感应器镜面对称了一下的话 左下角红色的地方是原始的的方格,剩下的三个格 ...

  5. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) C.Ray Tracing (模拟或扩展欧几里得)

    http://codeforces.com/contest/724/problem/C 题目大意: 在一个n*m的盒子里,从(0,0)射出一条每秒位移为(1,1)的射线,遵从反射定律,给出k个点,求射 ...

  6. Codeforces Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) A. Checking the Calendar(水题)

    传送门 Description You are given names of two days of the week. Please, determine whether it is possibl ...

  7. Codeforces Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) B. Batch Sort(暴力)

    传送门 Description You are given a table consisting of n rows and m columns. Numbers in each row form a ...

  8. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) B

    Description You are given a table consisting of n rows and m columns. Numbers in each row form a per ...

  9. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) A

    Description You are given names of two days of the week. Please, determine whether it is possible th ...

随机推荐

  1. 广度优先搜索(BFS)

    定义 维基百科:https://en.wikipedia.org/wiki/Breadth-first_search 给定图G=(V,E)和一个可识别的源结点s,广度优先搜索对图G中的边进行系统性的探 ...

  2. 深入了解try catch

    @Test public void testWeiXin(){ System.out.println(task()); } private boolean task(){ try { int i = ...

  3. VS2015 使用 Web Deploy 发布网站到 WindowsServer2008 R2服务器详解

    使用原因:由于开发期间需要将开发出的网站随时提交到服务器以便公司高层随时访问所以要求将开发出的网站每天发布到服务器,频繁度比较高,因此不能再使用之前的方式(发布到本地后再拷贝文件到服务器),所以想到了 ...

  4. python re模块

    re模块主要用于查找.替换.分割 print(re.__doc__) 特殊字符(元字符): "." 任意一个字符,除换行符(\n) "^" 字符串开头 &quo ...

  5. unreal slate 创建 window

    testWindow = SNew(SWindow) .Title(LOCTEXT("Asset Window", "Asset Window")) .Clie ...

  6. [转]SpringMVC拦截器简单教程

    亲测有用,地址: http://blog.csdn.net/tjcyjd/article/details/7498236

  7. Vue2随笔

    1. computed有缓存 methods没有缓存 慢慢更新中..... 2.Class与Style绑定 <div class="static" v-bind:class= ...

  8. 读文章《Flexbox详解》笔记

    文章地址:Flexbox详解 属性摘抄: flex container : display: other values | flex | inline-flex; flex-direction: ro ...

  9. Find命令的用法

    1. 在某目录下查找文件 [root@localhost ~]# find /usr/local -name pci.ids* /usr/local/share/pci.ids.gz [root@lo ...

  10. 命令行导入mysql数据

    找到mysql安装目录(bin) 进入mysql mysql -u root -p 123 选中数据库 use 数据库名 导入sql  source sql数据库路径