BestCoder Round #59 (div.2)

5 篇文章 0 订阅
5 篇文章 0 订阅

前言:

   受水平限制,仅能在比赛及其结束后写出前三题。

题目:

  • SDOI

    • 思路:就是纯模拟,只不过略为恶心。
    • 代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=105;
struct node
{
    string name;
    int sex,r1,r2;
    double ave;
    bool operator < (const node &a) const 
    {
        return ave>a.ave;
    }
};
int t,n,m,high1,high2;
bool flag;
node man[maxn];

void work()
{
    cout<<"The member list of Shandong team is as follows:"<<endl;
    sort(man+1,man+n+1);
    if (!flag)
    {
        for (int i=1;i<=m;++i)
          cout<<man[i].name<<endl;
    }
    else
    {
        bool in=0;
        int p=0;
        for (int i=1;i<=m-1;++i)
        {
            cout<<man[i].name<<endl;
            if (man[i].sex==1)
            {
                in=1;
            }
        }
        if (in==1)
        {
            cout<<man[m].name<<endl;
            return;
        }
        else
        {
            int p=m-1;
            while (true)
            {
                p++;
                if (man[p].sex==1)
                {
                    cout<<man[p].name<<endl;
                    return;
                }
            }           
        }
    }
}

void init()
{
    scanf("%d",&t);
    while (t--)
    {
        flag=0;
        high1=high2=0;
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;++i)
        {
            cin>>man[i].name;
            string s;
            cin>>s;
            if (s=="male")
              man[i].sex=0;
            else
            {
                man[i].sex=1;
                flag=1;
            }
            cin>>man[i].r1>>man[i].r2;
            high1=max(high1,man[i].r1);
            high2=max(high2,man[i].r2);
        }
        for (int i=1;i<=n;++i)
        {
            man[i].ave=((double)man[i].r1*(300.0/(double)high1))*0.3+((double)man[i].r2*(300.0/(double)high2))*0.7;
        }
        work();
    }   
}

int main()
{
    init();
    return 0;
}
  • Reorder The Books

    • 思路:可以发现,一定先操作大的数,再操作小的数。因为假如先把小的数放前面去了,再把大的数放前面去,小的数就又在大的数后面了,小的数必定还得再操作一次,然而操作两次是不划算的。同时可以发现最大的数 n 是不用操作的(其他数操作好了,数n自然就在最后面了)。 于是我们先找到最大的数 n 的位置,从这个位置往前找,直到找到(n1)。假如找到头也没找到 (n1) ,那么数 (n1) 需要操作,而一旦操作了 (n1) ,根据前面发现,总共就需要 (n1) 次操作了;假如找到了 (n1) ,那么数 (n1) 也不需要操作(和数 n 不需要操作一个道理)。 同理,我们接着从(n1)的位置往前找 (n2) ,再从 (n2) 的位置往前找 (n3) …假如数 k 找不到了,那么就至少需要k次操作。这种做法的复杂度是 O(n) 的。
    • 代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100;
int t,n,a[maxn];

int main()
{
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d",&n);
        int pos;
        bool f=0;
        for (int i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
            if (a[i]==n)
              pos=i;
        }
        for (int k=n-1;k>=0;--k)
        {
            if (k==0)
            {
                f=1;
                break;
            }
            bool flag=0;
            for (int i=pos;i>=1;--i)
            {
                if (a[i]==k)
                {
                    flag=1;
                    pos=i;
                    break;
                }
            }
            if (flag)
              continue;
            else
            {
                printf("%d\n",k);
                break;
            }
        }
        if (f)
        {
            printf("0\n");
        }
    }
    return 0;
}
  • The Highest Mark

    • 思路:贪心+动态规划。
    • 首先发现,交换相邻两个题目的做题顺序对其它题目是没有影响的。设两者从t=0时刻开始做,两题编号为1、2。先1后2,得分 score1=a[1]b[1]c[1]+a[2]b[2](c[1]+c[2])
      先2后1,得分 score2=a[2]b[2]c[2]+a[1]b[1](c[1]+c[2])
      若score1>score2,会有b[1]c[2]>b[2]c[1]即b[1]/c[1]>b[2]/c[2],那么以b[i]/c[i]为关键字由大到小进行排序(因为01背包对物品考虑顺序有先后)即可。
    • 最后就是01背包的事了,设f[j]代表用了时间j能取的最大得分,则有f[j]=max(f[j],f[j-c[i]]+a[i]-j*b[i])。

    • 代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
    int a,b,c;
    double d;
    bool operator < (const node &a) const
    {
        return d>a.d;
    }
};
const int maxn=1005;
int n,t,T;
node pro[maxn];
int f[3005];

void dp()
{
    memset(f,0,sizeof(f));
    sort(pro+1,pro+n+1);
    for (int i=1;i<=n;++i)
      for (int j=t;j>=pro[i].c;--j)
        f[j]=max(f[j],f[j-pro[i].c]+pro[i].a-j*pro[i].b);
    int ans=0;
    for (int i=0;i<=t;++i)
      ans=max(ans,f[i]);
    printf("%d\n",ans);
}

void init()
{
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d",&n,&t);
        for (int i=1;i<=n;++i)
        {
            scanf("%d%d%d",&pro[i].a,&pro[i].b,&pro[i].c);
            pro[i].d=(double)pro[i].b/(double)pro[i].c;
        }
        dp();
    }
}

int main()
{
    init();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值