hdu6024 - Building Shops - dp

http://acm.hdu.edu.cn/showproblem.php?pid=6024

题意:

有n个地点,最左边的地点一定要建一个商店,其他的地点可建可不建,

对于每个地点,建的话花费c[i],不建的话花费=这个地点的位置-在它左边的离它最近的商店的位置

求最小花费

思路:

dp[i][1]:=第i个地点建

dp[i][0]:=第i个地点不建

dp[i][1]=min(dp[i-1][0],dp[i-1][1])+c[i]

dp[i][0]=min(dp[1][1]+dis[1][i],dp[2][1]+dis[2][i]……dp[i-1][0]+dis[i-1][i])

翻译过来就是在第i个地点不建时,它左边的最近的点建的点是j(j<i),然后再加上距离(注意此时的距离是,j+1到j的距离+j+2到j的距离+……+i到j的距离)

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>
#include<functional>
using namespace std;
#define ll long long

typedef pair<ll,int>P;
const ll INF=1e17+10;
const int N=3005,mod=192;
struct A{
    ll x,c;
}fang[N];
ll dp[N][2];
ll dis[N][N];
bool cmp(A a,A b){
    return a.x<b.x;
}

int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        for(int i=1;i<=n;i++){
            scanf("%lld%lld",&fang[i].x,&fang[i].c);
        }
        sort(fang+1,fang+1+n,cmp);
        memset(dp,INF,sizeof(dp));
        dp[1][1]=fang[1].c;
        dp[1][0]=INF;
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                dis[i][j]=dis[i][j-1]+fang[j].x-fang[i].x;
            }
        }
        for(int i=2;i<=n;i++){
            dp[i][1]=min(dp[i-1][0],dp[i-1][1])+fang[i].c;
            for(int j=i-1;j>=1;j--){
                dp[i][0]=min(dp[i][0],dp[j][1]+dis[j][i]);
            }
        }
        printf("%lld\n",min(dp[n][1],dp[n][0]));
    }
}

遇到这种可建可不建的,就想到用第二维表示建与不建

猜你喜欢

转载自blog.csdn.net/m0_37579232/article/details/90142893