2017 CCPC-WFinal&&HDOJ 6024 Building Shops

xiaoxiao2021-02-28  88

Building Shops

Time Limit: 2000/1000 MS(Java/Others)    Memory Limit: 131072/131072 K(Java/Others) Total Submission(s): 0    Accepted Submission(s): 0

Problem Description

HDU’s n classrooms are on a line ,which can be considered as a number line.Each classroom has a coordinate. Now Little Q wants to build several candyshops in thesen classrooms. The total cost consists of two parts. Building a candy shop at classroom i would have some costci . For every classroomP without any candy shop, then the distance betweenP and the rightmost classroom with a candy shop onP 's left side would be included in the cost too. Obviously, if there isa classroom without any candy shop, there must be a candy shop on its leftside. Now Little Q wants to know how to build the candy shops with the minimal cost.Please write a program to help him.

 

 

Input

The input contains severaltest cases, no more than 10 test cases. In each test case, the first line contains an integer n(1≤n≤3000) , denoting the number of the classrooms. In the following n lines, each line contains two integersxi,ci(−109≤xi,ci≤109) , denoting the coordinate of thei -th classroom and the cost of building a candy shop in it. There are no two classrooms having same coordinate.

 

 

Output

For each test case, print asingle line containing an integer, denoting the minimal cost.

 

 

Sample Input

3

1 2

2 3

3 4

4

1 7

3 1

5 10

6 1

 

 

Sample Output

5

11

题意:给出一条直线上的若干点以及在该店建造商店的花费,求最小费用。最小费用由两部分组成,一部分是建造商店的花费(你可以选择每个点是否建造商店,不过要求没有建造商店每个点其左侧必须至少有一商店,显然,最靠左的点上必须建造商店),还有一部分是没有建造商店的点与其左侧最近商店的距离

思路:显然,这是一道动态规划的题目,但如果你只是每次单纯考虑当前点是否建造,那么这个动态规划就错了(本质已经变成了贪心),举个例子: 1 1), 35),1001000),10110000),10210000),10310000…20010000),显然,如果贪心过去第三个点肯定不取,但事实上,应该建造第一个点和第三个点。所以我们在考虑当前点时,用该重新考虑前面的建造情况

法一:

#include <bits/stdc++.h> using namespace std; #define mst(a,b) memset((a),(b),sizeof(a)) #define f(i,a,b) for(int i=(a);i<=(b);++i) #define ll long long const int maxn = 3005; const int mod = 1e9+7; const int INF = 0x3f3f3f3f; const double eps = 1e-6; #define rush() int T;scanf("%d",&T);while(T--) struct node { ll x,y; }a[maxn]; ll dp[maxn]; bool cmp(const node &a,const node &b) //比node a 更好的写法 {     return a.x<b.x; } int main() { int n; while(~scanf("%d",&n)) { for(int i=1; i<=n; i++) { scanf("%I64d%I64d",&a[i].x,&a[i].y); } sort(a+1,a+n+1,cmp); //使点按照坐标从左往右排序 dp[0]=0; for(int i=1; i<=n; i++) { dp[i]=INF; ll tot=0; for(int j=i; j>0; j--) { tot+=a[j].x; ll cost =a[j].y; //在j处建造商店 ll dis=tot-(i-j+1)*a[j].x; //j右侧所有点与j的距离和 dp[i]=min(dp[i],dp[j-1]+dis+cost); } } printf("%I64d\n",dp[n]); } return 0; }

法二:

状态转移方程:

   dp[i]=min(dp[i],sum[i]-sum[j]-(i-j)*(a[j].x-a[1].x)+dp[j-1]+a[j].y);

   其中sum[i]=a[i].x-a[1].x+sum[i-1];

#include <bits/stdc++.h> using namespace std; #define mst(a,b) memset((a),(b),sizeof(a)) #define f(i,a,b) for(int i=(a);i<(b);++i) typedef long long ll; const int maxn = 100005; const int mod = 475; const ll INF = 0x3f3f3f3f; const double eps = 1e-6; #define rush() int T;scanf("%d",&T);while(T--) int n; ll dp[maxn],sum[maxn]; struct node { ll x,y; }a[maxn]; bool cmp(const node &a,const node &b) { return a.x<b.x; } int main() { while(~scanf("%d",&n)) { mst(sum,0); for(int i=1;i<=n;i++) scanf("%I64d%I64d",&a[i].x,&a[i].y); sort(a+1,a+1+n,cmp); for(int i=1;i<=n;i++) { sum[i]=a[i].x-a[1].x+sum[i-1]; dp[i]=INF; } dp[1]=a[1].y; for(int i=2;i<=n;i++) for(int j=1;j<=i;j++) { dp[i]=min(dp[i],sum[i]-sum[j]-(i-j)*(a[j].x-a[1].x)+dp[j-1]+a[j].y); } printf("%I64d\n",dp[n]); } return 0; }

转载请注明原文地址: https://www.6miu.com/read-73436.html

最新回复(0)