问题描述
HDU的n个教室在一条线上,可以被认为是数字线。每个教室都有一个坐标。现在,小Q想在这些n个教室里建几个糖果店。
总成本由两部分组成。在教室里建一个糖果店我会有一些成本ci。对于没有任何糖果店的每个教室P,P和左边一个糖果店的最右边的教室之间的距离也将包含在成本中。显然,如果没有糖果店的教室,左侧必须有一个糖果店。
现在,小Q想以最低的成本知道如何建造糖果店。请写一个程序来帮助他。
输入
该输入包含几个测试用例,不超过10个测试用例。
在每个测试用例中,第一行包含整数n(1≤n≤3000),表示教室的数量。
在以下n行中,每行包含两个整数xi,ci(-109≤xi,ci≤109),表示第i个教室的坐标和建立糖果店的费用。
没有两个教室有相同的坐标。
输出
对于每个测试用例,打印包含整数的单行,表示最小成本。
样品输入
3
1 2
2 3
3 4
4
1 7
3 1
5 10
6 1
样品输出
5
HDU的n个教室在一条线上,可以被认为是数字线。每个教室都有一个坐标。现在,小Q想在这些n个教室里建几个糖果店。
总成本由两部分组成。在教室里建一个糖果店我会有一些成本ci。对于没有任何糖果店的每个教室P,P和左边一个糖果店的最右边的教室之间的距离也将包含在成本中。显然,如果没有糖果店的教室,左侧必须有一个糖果店。
现在,小Q想以最低的成本知道如何建造糖果店。请写一个程序来帮助他。
输入
该输入包含几个测试用例,不超过10个测试用例。
在每个测试用例中,第一行包含整数n(1≤n≤3000),表示教室的数量。
在以下n行中,每行包含两个整数xi,ci(-109≤xi,ci≤109),表示第i个教室的坐标和建立糖果店的费用。
没有两个教室有相同的坐标。
输出
对于每个测试用例,打印包含整数的单行,表示最小成本。
样品输入
3
1 2
2 3
3 4
4
1 7
3 1
5 10
6 1
样品输出
5
11
思路:看到本题很容易想到DP,但是很多时候不知不觉就搞成了贪心,贪心的想法为错误:
例子:
所以要正确的DP,明白第i项是否建立糖果屋不仅仅和第i-1项有关系,还和前面的项有关系,详解见代码3
1 1
100 100
101 1000
贪心:1+99+100=200
正解:1+100+1=102
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll INF = 1e18;
struct node
{
int pos;
int val;
}s[3005];
long long sum[3005][3005];
long long dp[3005][3]; //1为在i建立糖果屋,0为不建立
bool cmp(node x,node y)
{
return x.pos<y.pos;
}
int main()
{
int n;
while(scanf("%d",&n)==1)
{
for(int i=0;i<n;i++)
scanf("%d%d",&s[i].pos,&s[i].val);
sort(s,s+n,cmp); //万分注意,此题的一个坑
for(int i=0;i<n;i++){ //小位置
sum[i][i]=0;
for(int j=i+1;j<n;j++){ //大位置
sum[i][j]=sum[i][j-1]+s[j].pos-s[i].pos; //2个位置之间的距离
}
}
for(int i = 0;i<n;i++)
dp[i][1]=dp[i][0]=INF;
dp[0][1]=s[0].val;
for(int i=1;i<n;i++) //大位置
{
dp[i][1]=min(dp[i-1][1],dp[i-1][0])+s[i].val; //找出在第i建立糖果屋时候的最小值
for(int j=i-1;j>=0;j--) //小位置
dp[i][0] = min(dp[j][1] + sum[j][i],dp[i][0]);//找出在第i不建立糖果屋时候的最小值
}
printf("%lld\n",min(dp[n-1][0],dp[n-1][1]));
}
}