NEFU要崛起——第3场

比赛地址:http://acm.hust.edu.cn:8080/judge/contest/view.action?cid=17732#overview

第一题:给你一个数,看能不能分割成两个偶数

分析:水到不贴代码了。。。


第二题:给你一个数,能不能分割成n份,每份有上下限

分析:直接贪心搞定。。。


第三题:要求写一个注册系统,如果一个名字没出现过,就返回OK,如果出现过,就自动在末尾加数字,从1开始,直到这个新名字没出现过,并返回给用户,同时保存在数据库里。。。

分析:按这个题面描述,它是一道难题,不过由于题目是错的,所以只需要判断一个名字出现几次,在后面多输出那个次数就行。。。

为什么说题目错了呢?下面这组数据告诉你:

3

t1

t

t

这样,估计你们的程序都会输出

OK

OK

t1

呵呵,不解释了,反正因此我把他当难题,然后被虐成渣了大哭

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int mm=1000007;
struct hashtable
{
    int h[mm],p[mm],size;
    int d[111111];
    char s[111111][44];
    int hash(char *a)
    {
        int id=0;
        while(*a)id=id*131+(*a++);
        return (id&0x7FFFFFFF)%mm;
    }
    int insert(char *a)
    {
        int i,id=hash(a);
        for(i=h[id];i>=0;i=p[i])
            if(!strcmp(a,s[i]))return i;
        d[size]=1;
        strcpy(s[size],a);
        p[size]=h[id],h[id]=size++;
        return -1;
    }
    void clear()
    {
        size=0;
        memset(h,-1,sizeof(h));
    }
}g;
char str[44];
int i,n;
int main()
{
    while(~scanf("%d",&n))
    {
        g.clear();
        while(n--)
        {
            scanf("%s",str);
            i=g.insert(str);
            if(i<0)puts("OK");
            else
            {
                printf("%s%d\n",str,g.d[i]);
                ++g.d[i];
            }
        }
    }
    return 0;
}

第四题:这题就是要求一个最长序列,满足第i个信封的长和宽都严格大于第i-1封的长和宽,并且第一封要大于给的的卡片

分析:我们按每个信封的宽排序,如果宽相同,再按长排序,然后,你应该会发现,这个跟最长地增字序列很像,为什么说是很像,而不是一样呢,因为对于宽相同的是不能放在一起的。。。我之前忽略这个问题,加了二分优化,反而挂了= =

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int mm=111111;
struct data
{
    int w,h,id;
}g[mm];
int f[mm],p[mm];
int i,j,k,ans,n,w,h;
bool cmp(data a,data b)
{
    return a.w<b.w||(a.w==b.w&&a.h<b.h)||(a.w==b.w&&a.h==b.h&&a.id>b.id);
}
void out(int j)
{
    if(j<0)return;
    out(p[j]);
    printf("%d%c",g[j].id,--ans?' ':'\n');
}
int main()
{
    while(~scanf("%d%d%d",&n,&w,&h))
    {
        for(i=0;i<n;++i)
            scanf("%d%d",&g[i].w,&g[i].h),g[i].id=i+1;
        sort(g,g+n,cmp);
        for(i=0;i<n;++i)
            if(g[i].w>w&&g[i].h>h)f[i]=1;
            else f[i]=-1e7;
        for(i=0;i<n;++i)
            for(p[i]=-1,j=0;j<i;++j)
                if(g[j].w<g[i].w&&g[j].h<g[i].h&&f[j]+1>f[i])
                {
                    f[i]=f[j]+1;
                    p[i]=j;
                }
        for(i=j=0;i<n;++i)
            if(f[i]>f[j])j=i;
        ans=f[j];
        if(ans>0)
        {
            printf("%d\n",ans);
            out(j);
        }
        else puts("0");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值