【洛谷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;
}