HDU 6024(dp)

题目描述:

Building Shops

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


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 candy shops in these n classrooms.

The total cost consists of two parts. Building a candy shop at classroom i would have some cost ci. For every classroom P without any candy shop, then the distance between P and the rightmost classroom with a candy shop on P'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.
 

Input
The input contains several test cases, no more than 10 test cases.
In each test case, the first line contains an integer n(1n3000), denoting the number of the classrooms.
In the following n lines, each line contains two integers xi,ci(109xi,ci109), denoting the coordinate of the i-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 a single line containing an integer, denoting the minimal cost.
 

Sample Input
31 22 33 441 73 15 106 1
 

Sample Output
511
 

Source

 


    题目描述:有n个课室,每个课室都有一个坐标,要在这些课室中建糖果屋,在第i个课室间建糖果屋要花费c元。任意一个没有糖果屋的课室与左边第一个有糖果屋的课室的距离也得算入花费。问最少花费为多少。

    题目分析:因为要求没有糖果屋的课室左边必须要有糖果屋,故坐标最小的点(处于最左边的点)必定要建立。之后的糖果屋,因为存在可建和不建两种状态,故考虑采用dp去解决。
    我们设dp[i][j],i代表当前在i这个教室,j代表里i最近的教室的结点,因为有建和不建的可能性,故状态转移方程为:
    dp[i][j]=min(dp[i][j],dp[i-1][j]+did(i,j));
    dp[i][i]=min(dp[i][i],dp[i-1][j]+c[i]);
    附上代码:

    

#include <bits/stdc++.h>
#define maxn 3005
using namespace std;
typedef long long ll;
ll dp[maxn][maxn];
struct classes{
    ll x,c;
}q[maxn];
ll dis[maxn];
const ll INF=0x3f3f3f3f3f3f3f3f;
bool cmp(classes a,classes b){
    return a.x<b.x;
}
int main()
{
    int n;
    while(cin>>n){
        for(ll i=1;i<=n;i++){
            cin>>q[i].x>>q[i].c;
        }
        sort(q+1,q+1+n,cmp);
        memset(dp,INF,sizeof(dp));
        dp[1][1]=q[1].c;
        for(int i=2;i<=n;i++){
            for(int j=1;j<i;j++){
                dp[i][j]=min(dp[i][j],dp[i-1][j]+q[i].x-q[j].x);
                dp[i][i]=min(dp[i][i],dp[i-1][j]+q[i].c);
            }
        }
        ll res=INF;
        for(int i=1;i<=n;i++){
            res=min(res,dp[n][i]);
        }
        cout<<res<<endl;
    }
    return 0;
}

    当然,这道题还能够在进行优化,因为我们发现第二维的数组不一定需要,故可以将dp数组从二维改成一维的数组。
   

    首先先得预处理处理出排好序之后的各个结点的距离的前缀和dis[i]

    设dp[i]为处于i这个教室时的最小花费,状态转移方程为:
    dp[i]=min( min(dp[i] , dp[j-1]+c[j]+(dis[i]-dis[j] ) - (i-j)*x[j]) , dp[i-1] + c[i]);
    代码如下:
#include <bits/stdc++.h>
#define maxn 3005
using namespace std;
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
struct classes{
    ll c,x;
}q[maxn];
bool cmp(classes a,classes b){
    return a.x<b.x;
}
ll f[maxn];
ll dis[maxn];
int main()
{
    int n;
    while(cin>>n){
        memset(dis,0,sizeof(dis));
        for(int i=1;i<=n;i++){
            cin>>q[i].x>>q[i].c;
        }
        sort(q+1,q+1+n,cmp);
        for(int i=1;i<=n;i++){
            dis[i]=dis[i-1]+q[i].x;
        }
        memset(f,INF,sizeof(f));
        f[0]=0;
        f[1]=q[1].c;
        for(int i=2;i<=n;i++){
            for(int j=1;j<i;j++){
                f[i]=min(f[i],f[j-1]+q[j].c+(dis[i]-dis[j])-1ll*(i-j)*q[j].x);
            }
            f[i]=min(f[i],f[i-1]+q[i].c);
        }
        cout<<f[n]<<endl;
    }
    return 0;
}

posted @ 2018-04-20 22:54  ChenJr  阅读(204)  评论(0编辑  收藏  举报