Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Problem Description
HDU’s 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 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
3
1 2
2 3
3 4
4
1 7
3 1
5 10
6 1
 
Sample Output
5
11
 
dp[i]代表最后一个商店建在i的最小花费。当前状态是会影响后面的状态的,所以通过前面的状态进行更新是最好的选择.
所以就有dp[i]可以通过比i小的所有方案进行更新
dp[i]=dp[j]+save[i].cost-(n-i+1)*(save[i].pos-save[j].pos);
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<cmath>
#include<set>
#include<stack>
#define ll long long
#define max(x,y) (x)>(y)?(x):(y)
#define min(x,y) (x)>(y)?(y):(x)
#define cls(name,x) memset(name,x,sizeof(name))
using namespace std;
const int inf=1<<28;
const int maxn=3010;
const int maxm=110;
const int mod=1e9+7;
const double pi=acos(-1.0);
ll n;
struct node
{
    ll pos,cost;
    bool friend operator<(node a,node b)
    {
        return a.pos<b.pos;
    }
}save[maxn];
ll dp[maxn];
int main()
{
    //freopen("in1002.txt","r",stdin);
    while(~scanf("%lld",&n))
    {
        for(ll i=1;i<=n;i++)
            scanf("%lld %lld",&save[i].pos,&save[i].cost);
        sort(save+1,save+n+1);
        dp[1]=save[1].cost;
        for(ll i=2;i<=n;i++)
            dp[1]+=(save[i].pos-save[1].pos);
        //dp[i]表示最后一个商店建在i的最小花费
        for(ll i=2;i<=n;i++)
        {
            for(ll j=1;j<i;j++)
            {
                if(j==1)
                dp[i]=dp[j]+save[i].cost-(n-i+1)*(save[i].pos-save[j].pos);
                else
                dp[i]=min(dp[i],dp[j]+save[i].cost-(n-i+1)*(save[i].pos-save[j].pos));
            }
        }
        ll ans=dp[1];
        for(ll i=1;i<=n;i++)
            ans=min(ans,dp[i]);
        printf("%lld\n",ans);
    }
    return 0;
}

 

 /***2017.7.11更新***/
前不久学到了斜率优化,今天想起来这题可以用到,结果居然优化到了时间排名第一了,真是惊喜呀!

 

等有时间再讲讲斜率优化,就先把代码贴出来吧。
 
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<cmath>
#include<set>
#include<stack>
#define ll long long
#define pb push_back
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define cls(name,x) memset(name,x,sizeof(name))
#define pos first
#define cost second
#define mp make_pair
using namespace std;
const int inf=1e9+10;
const ll llinf=1e16+10;
const int maxn=3010;
const int maxm=1e2+10;
const int mod=1e9+7;
int n;
pair<ll,ll> shop[maxn];
ll dp[maxn];
double kfunc(int i,int j)
{
    return ((double)(dp[j]-dp[i]))/(shop[j].pos-shop[i].pos);
}
int main()
{
    //freopen("in.txt","r",stdin);
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)
        {
            ll a,b;
            scanf("%lld %lld",&a,&b);
            shop[i]=mp(a,b);
        }
        sort(shop+1,shop+n+1);
        dp[1]=shop[1].cost;
        for(int i=2;i<=n;i++)
            dp[1]+=(shop[i].pos-shop[1].pos);
        dp[2]=dp[1]+shop[2].cost-(n-2+1)*(shop[2].pos-shop[1].pos);
        int Q[maxn];
        int f=0,r=1;
        Q[0]=1;
        Q[1]=2;
        for(int i=3;i<=n;i++)
        {
            while(kfunc(Q[f],Q[f+1])<i-n-1 && r-f+1>2) f++;
            int j;
            if(kfunc(Q[f],Q[f+1])>i-n-1)
                j=Q[f];
            else j=Q[f+1];
            dp[i]=dp[j]+shop[i].cost-(shop[i].pos-shop[j].pos)*(n-i+1);
            if(kfunc(Q[r],i)>kfunc(Q[r-1],Q[r]))
            {
                Q[++r]=i;
            }
            else
            {
                while(r-f+1>1 && kfunc(Q[r],i)<kfunc(Q[r-1],Q[r]) )//可利用短路防止越界报错
                    r--;
                Q[++r]=i;
            }
        }
        ll ans=dp[1];
        for(ll i=1;i<=n;i++)
        {
            ans=min(ans,dp[i]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-12-21
  • 2021-08-30
  • 2022-02-04
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-06-11
  • 2022-12-23
  • 2021-07-11
  • 2022-01-08
相关资源
相似解决方案