NOIP2011 提高组 复赛 day1 hotel 选择客栈

NOIP2011 提高组 复赛 day1 hotel 选择客栈

1.结构体是少不了了,本题若用n^2,估计要超时,只能得50分。

2.按常规的做法,傻傻的找,肯定涉及n^2。

3.第一步,对合适的咖啡馆进行标记,

4.思路集中于扫描一遍,将答案算出。

5.受到最长上升子序列(动态规划中典型问题)启发,对i处,包括i之前每种颜色个数进行记录,开个二维数组。

6.合适的咖啡馆,可以放在结尾酒店,中间酒店,开始酒店三个位置,三个位置统计完毕后,该合适咖啡馆任务完成。

7.该合适咖啡馆下一个位置开始如上6情况进行雷同处理。

8.其实题目条件也有提示,2 ≤n ≤200,000,0<k ≤50,n*K<=10^7,开个二维数组,正合适。

9.思路清晰后,开始编码,估计能得100分。

10.按照思路,编码过程中,感觉很想用递归,但不熟练,还是先用非递归。

11.处理过程中,有无越界,+1还是-1感觉有点烦,耐着性子还是编好。

12.不放心啊,自个造了一组测试数据:

 输入:

5 2 3 
1 2 
1 3 
1 2 
1 3 
1 3 

输出:

10

经程序验证,成功。

13.怀着忐忑的心情,提交,AC。

一次成功。完全凭自身,没有参考任何东西,很是高兴,这个算法是磨出来的,跟积累是分不开的。

14.没完,想一想,用递归能不能实现。

15.网上搜了很多好解法,可惜功力不够,看不懂啊,暂且搁置,水平高了,再回头来看。

难度:中等偏难

好时:60分钟,(思考的时间有点长,先是一头雾水,后面才慢慢进入状态)

附上AC代码,编译环境Dev-C++4.9.9.2

//2011 hotel 很想用递归,但不熟练,还是先用非递归 
#include <stdio.h>
#include <string.h>
struct node{
    int color;
    int pay;
}h[200000+10];//旅馆信息 
int ka[200000+10];//符合提交咖啡馆 
int hc[200000+10][50+10];//统计i位置之前包括i位置颜色种类统计 
int main(){
    int n,k,p;
    int i,j,c;
    int kacount=0;
    int sum=0; 
    int before_pos,now_pos;
    memset(h,0,sizeof(h));
    memset(ka,0,sizeof(ka));
    memset(hc,0,sizeof(hc));
    scanf("%d%d%d",&n,&k,&p);
    for(i=1;i<=n;i++)
        scanf("%d%d",&h[i].color,&h[i].pay);
    for(i=1;i<=n;i++){//标记信息 
        if(h[i].pay<=p){
            kacount++;
            ka[kacount]=i;//统计符合条件的咖啡馆位置,从1开始 
        }
        hc[i][h[i].color]++;//统计i处的颜色情况。 
    }
    
    for(i=2;i<=n;i++){
        for(j=0;j<k;j++){
            hc[i][j]+=hc[i-1][j];//统计i处包括i之前颜色情况 
        }
    }
    ka[0]=0;//为了照顾数据处理,该处人为定义
    for(i=1;i<=kacount;i++){//对每个符合条件的咖啡馆做后,中,前位置处理。
         before_pos=ka[i-1];//之前符合条件,咖位啡馆置 
         now_pos=ka[i];//当前符合条件,咖位啡馆置 
         //该咖啡馆在最后
         if(now_pos-1>before_pos)
            sum+=(hc[now_pos-1][h[now_pos].color]-hc[before_pos][h[now_pos].color]);   
         //该咖啡馆在中间 
         if(now_pos-1>before_pos&&now_pos+1<=n){
                for(c=0;c<k;c++){
                    sum+=(hc[now_pos-1][c]-hc[before_pos][c])*(hc[n][c]-hc[now_pos][c]);
                }
         }
         //该咖啡馆在最前 
         if(now_pos+1<=n)
            sum+=(hc[n][h[now_pos].color]-hc[now_pos][h[now_pos].color]);
    }
    printf("%d\n",sum); 
    return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值