贪心EX
chc_1234567890 · · 题解
贪心是一种奇妙的算法,能将
国王游戏 link
本题需要高精,在此不细讲。
分析
我们考虑两个大臣
1.
| person | left | right |
|---|---|---|
2.
| person | left | right |
|---|---|---|
对于第一种情况,答案
对于第二种情况,答案
显然,
若
即
因此,若
按照上述条件sort一遍,再计算答案即可。
Code
#include<cstdio>
#define maxn 4010
using namespace std;
class hp{
public:
int a[maxn];
hp(){memset(a,0,sizeof(a));}
void clear(){memset(a,0,sizeof(a));}
hp(int x){
clear();
while(x){
a[++a[0]]=x%10;
x/=10;
}
while(a[a[0]]==0&&a[0])a[0]--;
}
hp& operator=(int x){
clear();
while(x){
a[++a[0]]=x%10;
x/=10;
}
while(a[a[0]]==0&&a[0])a[0]--;
return *this;
}
short cmp(const hp& x){
if(a[0]>x.a[0])return 1;
if(a[0]<x.a[0])return -1;
for(register int i=a[0];i>=1;i--){
if(a[i]>x.a[i])return 1;
if(a[i]<x.a[i])return -1;
}
return 0;
}
bool operator>(const hp& x){
return cmp(x)==1;
}
bool operator==(const hp& x){
return cmp(x)==0;
}
bool operator<(const hp& x){
return cmp(x)==-1;
}
bool operator>=(const hp& x){
return !(*this<x);
}
bool operator<=(const hp& x){
return !(*this>x);
}
hp operator-(const hp& x){
hp a=*this,c;
c.a[0]=a.a[0]>x.a[0]?a.a[0]:x.a[0];
for(register int i=1;i<=c.a[0];i++) {
c.a[i]+=a.a[i]-x.a[i];
if(c.a[i]<0){c.a[i]+=10;a.a[i+1]--;}
}
while(c.a[c.a[0]]==0&&c.a[0])c.a[0]--;
return c;
}
hp operator*(const hp& x){
hp c;
for(register int i=1;i<=a[0];i++){
for(register int j=1;j<=x.a[0];j++){
c.a[i+j-1]+=a[i]*x.a[j];
}
}
c.a[0]=a[0]+x.a[0];
for(register int i=1;i<=c.a[0];i++){
if(c.a[i]>=10){
c.a[i+1]+=c.a[i]/10;
c.a[i]%=10;
}
}
while (c.a[c.a[0]]==0&&c.a[0]>0)c.a[0]--;
return c;
}
hp operator/(const int& x){
hp c;
int t=0,s=0;
bool flag=1;
for(register int i=a[0];i>=1;i--){
t=s*10+a[i];
if(t/x>0||t==0){
c.a[++c.a[0]]=t/x;
s=t%x;
flag=0;
}
else{
s=t;
if(!flag)c.a[++c.a[0]]=0;
}
}
reverse(c.a+1,c.a+c.a[0]+1);
return c;
}
};
struct node{
int a,b;
};
node a[1001];
bool cmp(node x,node y){
return x.a*x.b<y.a*y.b;
}
void checkmax(hp& x,hp y){
if(x<y)x=y;
}
int main(){
int n;scanf("%d",n);
for(register int i=0;i<=n;i++){
scanf("%d%d",a[i].a,a[i].b);
}
sort(a+1,a+n+1,cmp);
hp ans=0,ji=a[0].a;
for(register int i=1;i<=n;i++){
checkmax(ans,ji/a[i].b);
ji=ji*a[i].a;
}
if(ans.a[0]==0)putchar('0');
else for(register int i=ans.a[0];i>=1;i--)
putchar(ans.a[i]+'0');
return 0;
}
补充题目:打CF
题意
一场CF比赛,时间为
第
这是一场比较dark的CF,分数可能减成负数
已知第
请问最多可以得到多少分
数据范围
分析
贪心思维题。
声明:在下面的分析中,我们约定
#define a maxPoints
#define b pointsPerMinute
#define c requiredTime
我们考虑两道题
若
而
按照此条件对每一道题排序。
设做掉题目
但由于比赛有时间限制,且题目最终得分可能为负数,因此,需要使用01背包来选择。转移方程:
Code
#include<cstdio>
#define maxn 55
#define maxt 100005
using namespace std;
typedef long long D;
inline D max(D x,D y){return x>y?x:y;}
D a[maxn],b[maxn],c[maxn],tot,dp[maxt],ans;
int cnt,n,t[maxn];
bool cmp(int i,int j){
return b[j]*c[i]<b[i]*c[j];
}
int main(){
scanf("%d%lld",n,tot);
for(int i=1;i<=n;i++)scanf("%lld",a[i]);
for(int i=1;i<=n;i++)scanf("%lld",b[i]);
for(int i=1;i<=n;i++)scanf("%lld",c[i]),t[i]=i;
sort(t+1,t+n+1,cmp);
for(int i=1;i<=n;i++){
for(int j=tot;j>=c[t[i]];j--){
dp[j]=max(dp[j],dp[j-c[t[i]]]+a[t[i]]-b[t[i]]*j);
ans=max(ans,dp[j]);
}
}
printf("%lld\n",ans);
return 0;
}