woj 1537 Stones I

题目地址: 戳这里

这是个比较好的思维题 ,简单但是有意思;

题面叙述不是很清楚

但是最后转化为数学模型就是:

选出一个k元子集(不妨设为1,2,3,...,k)

使得 a[1]-b[1]-b[2]-...-b[k];

       +a[2]-b[1]-b[2]-...-b[k];

       +a[3]-b[1]-b[2]-...-b[k];

       +...

       +a[k]-b[1]-b[2]-...-b[k];

       是最大的。

公式变形一下,就是sigma a[i]-k*b[i];

可以看见,这k个数选进来的顺序是没有影响的,而且必定是最大的k个(a[i]-k*b[i])  ,否则就可以替换使之更大。

然后就暴力枚举k了,关于每一项都必须是正数,证明是显然的。

代码:

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

int a[1005];
int b[1005];
int c[1005];

int ans[1005];

bool cmp(int a,int b)
{
    return a>b?1:0;
    
}
int main()
{
    int n;
    while(cin>>n)
    {
        if(!n)  break;
  
        memset(c, 0, sizeof(c));
        memset(ans, 0, sizeof(ans));
        
    for(int i=0;i<n;i++)
    {
        cin>>a[i]>>b[i];
        
    }
    
    for(int k=0;k<=n;k++)
    {
        for(int i=0;i<n;i++)
            c[i]=a[i]-k*b[i];
        
        sort(c,c+n,cmp);
        if(c[k-1]<0)  continue;
        for(int i=0;i<k;i++)
            ans[k]+=c[i];
        
    }
    
        int max=-1;
    
        for(int i=0;i<=n;i++)
            if(ans[i]>max) max=ans[i];
        
        cout<<max<<endl;
        
    }
 
}

  

posted on 2014-03-31 00:15  814jingqi的ACM  阅读(237)  评论(0编辑  收藏  举报