【题解】洛谷P1080国王游戏[NOIP2012Day1T2] 贪心

题目链接
按照每个大臣左右手上的数的乘积从小到大排序,就是最优排队方案
可以使用微扰证明,详见李煜东的算法竞赛进阶指南

#include
#include
#include
using namespace std;
struct node{
    int a,b,c;
}q[2000];
int a1[2000],b1[2000],c1[2000];
void mul(int a1[],int x){
    int j=0,i,t;
    for(i=1;i<=a1[0]||j;i++){
        t=a1[i]*x+j;
        j=t/10000;
        a1[i]=t%10000;
    }
    a1[0]=i-1;
}
void div(int a1[],int x){
    int i,j=0,t;
    for(i=a1[0];i>=1;i--){
        t=a1[i]+j*10000;
        b1[i]=t/x;
        j=t%x;
    }
    for(i=a1[0];i>=1;i--)if(b1[i]!=0)break;
    if(i==0)b1[0]=1;
    else b1[0]=i;
}
int cmp(const node&x,const node&y){
    return x.c<y.c;
}
int cmp1(int b1[],int a1[]){
    if(b1[0]!=a1[0])return b1[0]-a1[0];
    for(int i=b1[0];i>=1;i--)
    if(b1[i]!=a1[i])return b1[i]-a1[i];
    return 0;
}
int main(){
    //freopen("testdata.in","r",stdin);
    memset(c1,0,sizeof(c1));
    int i,n,a,b;
    scanf("%d%d%d",&n,&a,&b);
    for(i=1;i<=n;i++){
        scanf("%d%d",&q[i].a,&q[i].b);
        q[i].c=q[i].a*q[i].b;
    }
    sort(q+1,q+1+n,cmp);
    a1[0]=1;a1[1]=a;c1[0]=1;
    for(i=1;i<=n;i++){
        div(a1,q[i].b);
        if(cmp1(b1,c1)>0)
        memcpy(c1,b1,(b1[0]+1)*sizeof(int));
        mul(a1,q[i].a);
    }
    printf("%d",c1[c1[0]]);
    for(i=c1[0]-1;i>=1;i--)
    printf("%04d",c1[i]);
    printf("\n");
    return 0;
}

你可能感兴趣的:(算法竞赛进阶指南,洛谷,NOIP,贪心)