首页 > 代码库 > NOIP201106选择客栈

NOIP201106选择客栈

(本来像这种东西我都是写进程序注释里的,然而杨老师说不写就罚跑圈。。所以只能写了QAQ)

第一次写博,感觉没毛线好写的,贴道水题好了QAQ(其实是因为看WXJ和LJX围着这题的测试数据讨论了半个多小时屁结论都没有)

 

NOIP201106选择客栈
难度级别:A; 运行时间限制:1000ms; 运行空间限制:51200KB; 代码长度限制:2000000B
试题描述
   丽江河边有n家很有特色的客栈,客栈按照其位置顺序从1到n编号。每家客栈都按照某一种色调进行装饰(总共k种,用整数0到k-1表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费。两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中。晚上,他们打算选择一家咖啡店喝咖啡,要求咖啡店位于两人住的两家客栈之间(包括他们住的客栈),且咖啡店的最低消费不超过p。他们想知道总共有多少种选择住宿的方案,保证晚上可以找到一家最低消费不超过p元的咖啡店小聚。
输入
共n+1行。第一行三个整数n,k,p,每两个整数之间用一个空格隔开,分别表示客栈的个数,色调的数目和能接受的最低消费的最高值;接下来的n行,第i+1行两个整数,之间用一个空格隔开,分别表示i号客栈的装饰色调和i号客栈的咖啡店的最低消费。
输出
输出只有一行,一个整数,表示可选的住宿方案的总数。
输入示例
5 2 3
0 5
1 3
0 2
1 4
1 5
输出示例
3
其他说明
【输入输出样例说明】
客栈编号 ① ② ③ ④ ⑤
色调 0 1 0 1 1
最低消费 5 3 2 4 5
2人要住同样色调的客栈,所有可选的住宿方案包括:住客栈①③,②④,②⑤,④⑤,但是若选择住4、5号客栈的话,4、5号客栈之间的咖啡店的最低消费是4,而两人能承受的最低消费是3元,所以不满足要求。因此只有前3种方案可选。

【数据范围】2≤n≤200,000,0<k≤50,0≤p≤100, 0≤最低消费≤100。

这道题第一眼看上去就是直接O(n^3)的暴力,不过这不是找跪吗。。。

第二眼看上去。。求方案数直接dp不就行了嘛,Time O(nk)。。网上一堆dp烂在那。。

然而最近考完试一直颓在家里打游戏已经不会写dp了。。(QAQ杨老师表打我)

第三眼。。好了正解来了,智商还是有的。。

首先我们先随便找一个客栈,记为i号客栈。然后往左看,如果左边有一家咖啡店的最低消费<=两人可以承受的范围(我就不明白哪里来的最低消费,去咖啡店里接杯开水蹲马路边上喝不也一样吗)则继续从这个咖啡店往左看,如果找到一家颜色与i号相同的客栈则方法数+1。这样问题就转化成了左边有多少家客栈和当前这家同色,并且两家客栈之间有一家咖啡店的最低消费不超过p。。

注意只要从i号往左找到第一个符合要求的咖啡店后,就不需要再管咖啡店的事了。。从这个咖啡店向左搜索得出的方法数一定是对于i号而言最优的。。(如果这都想不明白那还是去嗑点nc片好了)

好了上代码,内有解释(QAQ我还是太善良) 

//a[i]记录i种颜色酒店所出现的最后一次的位置,只需开到Max_k即可; //b[i]记录i种颜色酒店的出现次数,大小同a; //c[i]临时记录当前i颜色的酒店出现的次数,大小同a,b。 //要不说这个算法速度快空间小,还不费脑子#include<iostream>#include<cstdio>using namespace std;int a[100],b[100],c[100];int main(){    int n,k,p,tmp,ans=0;    scanf("%d%d%d",&n,&k,&p); //输入,k没什么用     for(int i=0;i<n;i++)     {        int color,micost;        scanf("%d%d",&color,&micost); //输入i号酒店的颜色及咖啡店最小花费,注意不需要记录         if(micost<=p) tmp=i; //tmp记录当前color颜色酒店左边最后一个花费小于p的咖啡店的编号         if(tmp>=a[color]) c[color]=b[color];         //若tmp在color颜色酒店刚才出现最后一次的位置的右边,则条件符合,        //tmp左边的酒店数b[color]就是这一轮的答案,赋给c[color]         a[color]=i; //更新color颜色酒店最后一次出现的位置为i         ans+=c[color]; //答案累加上c[color],如果条件符合则c[color]为b[color],不符合则c[color]为0         b[color]++; //color颜色酒店出现次数多了一次,b[color]++     }     printf("%d",ans); //输出     return 0;}

致读者:我写博一定尽量让大家看懂(要不写它干嘛),不过毕竟本人初一水平有限,如果某些地方看不懂可以上网查询,自己模拟或者再看一遍。(不是逗你玩,当初我看拓补和微积分的时候第一遍怎么都看不懂,第二,三遍还是看不懂,一直看了七八遍才理解概念QAQ)如果读者发现哪里有问题可以随时给我发消息,若内容确实有误一定会再次修正。

 

NOIP201106选择客栈