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]));
}
}
遇到这种可建可不建的,就想到用第二维表示建与不建