DP【洛谷P2134】 百日旅行

【洛谷P2134】 百日旅行

题目背景

重要的不是去哪里,而是和你在一起。——小红

对小明和小红来说,2014年7月29日是一个美好的日子。这一天是他们相识100天的纪念日。

(小明:小红,感谢你2场大考时默默的支持,100个日夜的陪伴;感谢你照亮我100个美好的日子,给我留下无数美好的回忆……在这个美好的日子里,我准备带你去旅行。)

题目描述

小明和小红还剩下N天的假期,小明可以安排旅行的计划。如果连续X天旅游,小明需要花旅行费用\(P*X*X\)元;如果连续X天不旅游,小明需要请小红吃饭,花费为Q*X元。(P,Q都是输入的常数)

请你帮小明写一个程序,计算出假期里他至少需要花费多少元。

输入输出格式

输入格式:

一行,3个空格隔开的正整数N,P,Q。

输出格式:

一行,一个正整数表示小明至少需要花费多少元。

经过分析,可以发现对于吃饭,我们只在乎它的时间总量,然后对于旅行,我们已经知道旅行的时间是n-吃饭的时间,又因为计算公式中含有平方,所以我们需要关心这n-i的时间分成了几段。

这样就可以开始写\(n^2\)的算法了。

第一层枚举吃饭时间,第二层枚举旅行时间分为多少段,\(O(1)\)计算即可。

code:

#include<iostream>
#include<cstdio>
using namespace std;
inline int read(){
    int sum=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
    return sum*f; 
}
int n,p,q,ans=2147483647;
int main(){
    n=read();p=read();q=read();
    if(q<=p){
        printf("%d\n",n*q);
        return 0;
    }
    for(int i=0;i<=n;i++){
        for(int j=1;j<=min(n-i,i+1);j++){
//          int j=i+1;
            int tmp=i*q+((n-i)/j+1)*((n-i)/j+1)*p*((n-i)%j)+((n-i)/j)*((n-i)/j)*p*(j-(n-i)%j);
            ans=min(ans,tmp);
        }
    }
    printf("%d\n",ans);
    return 0;
}

写完就可以发现最优情况下旅行的时间被平均分是最好的,所以找到了凸性函数的极值点直接带就可以了。

100分

code:

#include<iostream>
#include<cstdio>
using namespace std;
inline int read(){
    int sum=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
    return sum*f; 
}
int n,p,q,ans=2147483647;
int main(){
    n=read();p=read();q=read();
    if(q<=p){
        printf("%d\n",n*q);
        return 0;
    }
    for(int i=0;i<=n;i++){
            int j=i+1;
            int tmp=i*q+((n-i)/j+1)*((n-i)/j+1)*p*((n-i)%j)+((n-i)/j)*((n-i)/j)*p*(j-(n-i)%j);
            ans=min(ans,tmp);
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wangxiaodai/p/9776036.html