记录一个菜逼的成长。。
题目大意:
n个教室,选一些教室建造糖果商店。
每个教室,有一个坐标
xi
和在这个教室建造糖果商店的花费
ci
对于每一个教室,如果这个教室建造糖果商店,花费就是
ci
,否则就是与坐标在自己前面的建造糖果商店的距离
求最小花费
这题一开始想的贪心,但是是错的。
比如
3
1 1
10 10
11 99
考虑dp
dp[i][1]:=表示第i个教室建造糖果商店的最小花费
dp[i][0]:=表示第i个教室不建造糖果商店的最小花费
对于
dp[i][1]
有如下状态转移
dp[i][1]=min(dp[i−1][1],dp[i−1][0])
对于
dp[i][0]
有如下状态转移
枚举上一个建造糖果商店的教室
dp[i][0]=min(dp[i−1][0],dp[j][1]+sum)(1≤j<i)
(sum是第j+1个教室到第i个教室与第j个教室的距离之和)
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define cl(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<LL,LL> PLL;
const int maxn = 3000 + 10;
PLL a[maxn];
LL dp[maxn][2];
int main()
{
int n;
while(~scanf("%d",&n)){
cl(dp,0x3f3f3f3f);
for( int i = 1; i <= n; i++ ){
scanf("%lld%lld",&a[i].fi,&a[i].se);
}
sort(a+1,a+1+n);
dp[1][1] = a[1].se;
for( int i = 2; i <= n; i++ ){
dp[i][1] = min(dp[i-1][1],dp[i-1][0]) + a[i].se;
LL tmp = 0;
for( int j = i-1; j > 0; j-- ){
tmp += (i-j) * (a[j+1].fi - a[j].fi);
dp[i][0] = min(dp[j][1]+tmp,dp[i][0]);
}
}
printf("%lld\n",min(dp[n][1],dp[n][0]));
}
return 0;
}