HDU 6024 女生专场)Building Shops

HDU’s  nn 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 candy shops in these  nn classrooms. 

The total cost consists of two parts. Building a candy shop at classroom  ii would have some cost  cici. For every classroom  PP without any candy shop, then the distance between  PP and the rightmost classroom with a candy shop on  PP's left side would be included in the cost too. Obviously, if there is a classroom without any candy shop, there must be a candy shop on its left side. 

Now Little Q wants to know how to build the candy shops with the minimal cost. Please write a program to help him. 
InputThe input contains several test cases, no more than 10 test cases. 
In each test case, the first line contains an integer  n(1n3000)n(1≤n≤3000), denoting the number of the classrooms. 
In the following  nn lines, each line contains two integers  xi,ci(109xi,ci109)xi,ci(−109≤xi,ci≤109), denoting the coordinate of the  ii-th classroom and the cost of building a candy shop in it. 
There are no two classrooms having same coordinate.OutputFor each test case, print a single 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;



题意: 
有n个教室,现在想在这n个教室中建一些超市,问你最少费用为多少? 
费用分为两种: 
1:在第i个教室建超市,费用因为ci 
2:没有建超市的教室的费用为它和它左边最接近的超市的坐标之间的距离

分析: 
根据题目所给的时间,和题目的数据的大小,我们可以知道题目可以承受住时间复杂度为O(n^2)的算法。

并且每个教室只有两种方案,要么建超市,要么不建。这就很像是背包问题了,所以我们就想到了dp.

我们设dp[i][0]表示在教室i不建超市时前i个教室的费用和的最小值;dp[i][1]表示在教室i建超市时前i个教室的费用和的最小值

那么我们很快可以得出: dp[i][1] = min(dp[i-1][0],dp[i-1][1]) + ci

关于dp[i][0],由于可以承受住时间复杂度为O(n^2)的算法,那么我们就可以想到枚举离教室i最近的超市j的位置,然后取所有情况的最小值就可以了。

假设左边最近超市为j,那么教室j+1~教室i都不能建超市,所以教室j+1~教室i的费用分别为他们的位置到教室j之间的距离了。当前dp[i][0] = dp[j][1] +( 教室j+1~教室i的费用)

如果我们暴力求解,那么时间复杂度会变成O(n^3),会超时。但是我们会发现由于j是从大到小变化的,所以就可以用:t += (i - j) * (nodes[j+1].x - nodes[j].x);来记录教室j+1~教室i的费用和了。

关于 t += (i - j) * (nodes[j+1].x - nodes[j].x); 的解释: 

比如我们要算x3 - x1 , x2 - x1的sum,那么由于保证了x是升序排列的,所以sum = (x3 - x2) + 2 * (x2 - x1).


睡了一觉写的AC码~当然很大一部分是摸出来的啦


#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int maxn = 4000;
struct node
{
    long long x,c;
}nobb[maxn];

bool cmp(node a,node b)
{
return a.x < b.x;
}
LL dp[maxn][maxn];

LL f = 100000000000;
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i = 1;i <= n;i++)
{
scanf("%lld %lld",&nobb[i].x,&nobb[i].c);
}
sort(nobb + 1,nobb + 1 + n,cmp);
dp[1][0] = f;
dp[1][1] = nobb[1].c;
for(int i = 2;i <= n;i++)
{
dp[i][1] = min(dp[i - 1][0],dp[i -1][1]) + nobb[i].c;
dp[i][0] = f;
LL t = 0;
for(int j = i - 1;j > 0;j--)
{
t += (i - j) * (nobb[j + 1].x - nobb[j].x);
dp[i][0] = min(dp[i][0],dp[j][1] + t);
}
}
printf("%lld\n",min(dp[n][0],dp[n][1]));
}
}


猜你喜欢

转载自blog.csdn.net/strawberry_595/article/details/80358102