题意
有n个教室排成一排,每个教室都有一个坐标,现在,小Q想建一些糖果商店,在这n个教室里面。总的花费有两部分,在教室i建一个糖果屋需要花费ci,对于没有任何糖果屋的P,需要的花费为这个教室到它左边有糖果商店的距离。怎么建糖果商店才能使花费最少?n<=3000.
分析
比较显然的dp,每个教室有两种选择,建糖果教室或者 不建糖果教室。f[i][0]第i个教室不建糖果商店时的最少花费。f[i][1]第i个教室建糖果商店时的最少花费。直接转移的话复杂度时O(N^3)的。我们可以预处理出所有i,j直接的距离的和。嗯,就酱~
对了,据说当时场上ltx大佬把这个转换成了树形dp???
玄学:vj上提交的时候G++可以AC,但是C++会WA
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 6 using namespace std; 7 const int maxn=3000+10; 8 const int INF=1e14; 9 struct Node{ 10 long long x,c; 11 bool operator <(const Node& rhs)const{ 12 return x<rhs.x; 13 } 14 }node[maxn]; 15 int n; 16 long long f[maxn][3],sum[maxn][maxn]; 17 int main(){ 18 while(scanf("%d",&n)!=EOF){ 19 for(int i=1;i<=n;i++){ 20 scanf("%lld%lld",&node[i].x,&node[i].c); 21 } 22 sort(node+1,node+1+n); 23 memset(sum,0,sizeof(sum)); 24 for(int i=1;i<=n;i++){ 25 sum[i][i]=0; 26 for(int j=i+1;j<=n;j++){ 27 sum[i][j]=sum[i][j-1]+node[j].x-node[i].x; 28 } 29 } 30 /* for(int i=1;i<=n;i++){ 31 for(int j=i+1;j<=n;j++){ 32 printf("%d--%d:%d\n",i,j,sum[i][j]); 33 } 34 }*/ 35 for(int i=1;i<=n;i++){ 36 f[i][0]=f[i][1]=INF; 37 } 38 f[1][1]=node[1].c; 39 for(int i=2;i<=n;i++){ 40 f[i][1]=min(f[i-1][0],f[i-1][1])+node[i].c; 41 f[i][0]=f[i-1][1]+node[i].x-node[i-1].x; 42 for(int j=1;j<i;j++){//在j处建 43 f[i][0]=min(f[i][0],f[j][1]+sum[j][i]); 44 } 45 } 46 long long ans=min(f[n][1],f[n][0]); 47 printf("%lld\n",ans); 48 // for(int i=1;i<=n;i++){ 49 // printf("%d:%lld %lld\n",i,f[i][0],f[i][1]); 50 //} 51 } 52 return 0; 53 }
原文地址:https://www.cnblogs.com/LQLlulu/p/8955246.html
时间: 2024-10-11 16:54:19