对拍练习:选择客栈(NOIP 2011)
2016-11-15 23:05
381 查看
题目描述
丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号。每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费。
两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中。晚上,他们打算选择一家咖啡店喝咖啡,要求咖啡店位于两人住的两家客栈之间(包括他们住的客栈),且咖啡店的最低消费不超过 p 。
他们想知道总共有多少种选择住宿的方案,保证晚上可以找到一家最低消费不超过 p元的咖啡店小聚。
输入输出格式
输入格式:
输入文件hotel.in,共n+1 行。
第一行三个整数n ,k ,p,每两个整数之间用一个空格隔开,分别表示客栈的个数,色调的数目和能接受的最低消费的最高值;
接下来的n 行,第 i+1 行两个整数,之间用一个空格隔开,分别表示 i 号客栈的装饰色调和i 号客栈的咖啡店的最低消费。
输出格式:
输出文件名为hotel.out 。
输出只有一行,一个整数,表示可选的住宿方案的总数。
输入输出样例
输入样例#1:
5 2 3
0 5
1 3
0 2
1 4
1 5
输出样例#1:
3
说明
【输入输出样例说明】
2 人要住同样色调的客栈,所有可选的住宿方案包括:住客栈①③,②④,②⑤,④⑤,但是若选择住4 、5 号客栈的话,4 、5 号客栈之间的咖啡店的最低消费是4 ,而两人能承受的最低消费是3 元,所以不满足要求。因此只有前 3 种方案可选。
【数据范围】
对于30% 的数据,有 n ≤100;
对于50% 的数据,有 n ≤1,000;
对于100%的数据,有 2 ≤n ≤200,000,0 < k ≤50,0≤p ≤100 , 0 ≤最低消费≤100。
【exercise】
以前就写过选择客栈…感觉60分的O(n^3)暴力非常好打…但是这道题的细节处理比较多…于是我就用这道题练习对拍了
对拍步骤挺简单:
1.写一个正解
2.写一个暴力
3.写一个rand
4.写一个对拍代码
【暴力】
先放一个通俗易懂的 暴力.cpp
好…现在把暴力输出到 暴力.txt 里了
【正解】
现在我尝试写一下正解…
将正解输出到 hotel.txt 里去
【rand】
再看一下rand怎么写
就是一堆随机化…随机出来的数输出到一个文件 rand.txt 里去
注意头文件要写 ctime
【对拍】
最后看一下对拍函数
需要用到 cstdlib 头文件
这四个程序都是要运行的,先运行前三个,最后运行对拍
双击对拍即可运行
【运行结果】
如果没有差异就是这个样子的~
有差异的话就是下面这样
有差异的话说明正解有问题,这时候根据 rand.txt 里的数据调试自己的正解程序就好啦。一开始先把rand函数里的数据造的小一点,便于调试,一直到无误以后再调试大数据。
希望可以对大家有帮助。谢谢。
丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号。每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费。
两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中。晚上,他们打算选择一家咖啡店喝咖啡,要求咖啡店位于两人住的两家客栈之间(包括他们住的客栈),且咖啡店的最低消费不超过 p 。
他们想知道总共有多少种选择住宿的方案,保证晚上可以找到一家最低消费不超过 p元的咖啡店小聚。
输入输出格式
输入格式:
输入文件hotel.in,共n+1 行。
第一行三个整数n ,k ,p,每两个整数之间用一个空格隔开,分别表示客栈的个数,色调的数目和能接受的最低消费的最高值;
接下来的n 行,第 i+1 行两个整数,之间用一个空格隔开,分别表示 i 号客栈的装饰色调和i 号客栈的咖啡店的最低消费。
输出格式:
输出文件名为hotel.out 。
输出只有一行,一个整数,表示可选的住宿方案的总数。
输入输出样例
输入样例#1:
5 2 3
0 5
1 3
0 2
1 4
1 5
输出样例#1:
3
说明
【输入输出样例说明】
2 人要住同样色调的客栈,所有可选的住宿方案包括:住客栈①③,②④,②⑤,④⑤,但是若选择住4 、5 号客栈的话,4 、5 号客栈之间的咖啡店的最低消费是4 ,而两人能承受的最低消费是3 元,所以不满足要求。因此只有前 3 种方案可选。
【数据范围】
对于30% 的数据,有 n ≤100;
对于50% 的数据,有 n ≤1,000;
对于100%的数据,有 2 ≤n ≤200,000,0 < k ≤50,0≤p ≤100 , 0 ≤最低消费≤100。
【exercise】
以前就写过选择客栈…感觉60分的O(n^3)暴力非常好打…但是这道题的细节处理比较多…于是我就用这道题练习对拍了
对拍步骤挺简单:
1.写一个正解
2.写一个暴力
3.写一个rand
4.写一个对拍代码
【暴力】
先放一个通俗易懂的 暴力.cpp
//选择客栈 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define M(a) memset(a,0,sizeof a) #define fo(i,j,k) for(i=j;i<=k;i++) using namespace std; const int T=200001; int n,k,p,mip,ans; int color[T],low[T],pre[51],shu[51]; int main() { freopen("rand.txt","r",stdin); //rand下文会提到 freopen("暴力.txt","w",stdout); int i,j,k; scanf("%d%d%d",&n,&k,&p); fo(i,1,n) { scanf("%d%d",&color[i],&low[i]); shu[color[i]]++; } fo(i,1,n) fo(j,i+1,n) if(color[i]==color[j]) { int l=i,r=j,mip=1e8; fo(l,i,j) { mip=min(mip,low[l]); if(mip<=p) { ans++; break; } } } cout<<ans; return 0; }
好…现在把暴力输出到 暴力.txt 里了
【正解】
现在我尝试写一下正解…
//选择客栈正解 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long #define fo(i,j,k) for(i=j;i<=k;i++) using namespace std; const int mxn=200005; int n,m,p; ll ans; int c[mxn],a[mxn],num[100]; int main() { freopen("rand.txt","r",stdin); freopen("hotel.txt","w",stdout); int i,j,k,ans=0; scanf("%d%d%d",&n,&m,&p);m--; fo(i,1,n) scanf("%d%d",&c[i],&a[i]),num[c[i]]++; fo(k,0,m) //枚举颜色 { int pre=0,sum=0; bool flag=0; fo(i,1,n) if(c[i]==k) break; fo(i,i,n) { if(a[i]<=p) flag=1; if(c[i]!=k) continue; pre++;sum++; if(a[i]<=p) { ans+=(ll)(pre-1)*(ll)(num[k]-sum+1)+num[k]-sum; pre=0;flag=0; fo(i,i+1,n) if(c[i]==k) {i=i-1;break;} } else if(flag) { ans+=(ll)(pre-1)*(ll)(num[k]-sum+1); pre=0;flag=0;i--;sum--; } } } cout<<ans<<endl; return 0; }
将正解输出到 hotel.txt 里去
【rand】
再看一下rand怎么写
//rand #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<ctime> #define M(a) memset(a,0,sizeof a) #define fo(i,j,k) for(i=j;i<=k;i++) using namespace std; int main() { freopen("rand.txt","w",stdout); srand(time(0)); //这步必须加上,我也不知道为啥 int n,m,p,i,j; n=rand()%1000+1; m=30; p=rand()%100; printf("%d %d %d\n",n,m,p); fo(i,1,n) printf("%d %d\n",rand()%30,rand()%100); return 0; }
就是一堆随机化…随机出来的数输出到一个文件 rand.txt 里去
注意头文件要写 ctime
【对拍】
最后看一下对拍函数
需要用到 cstdlib 头文件
//对拍 #include<cstdio> #include<cstring> #include<ctime> #include<cstdlib> #include<iostream> #include<algorithm> #define ll long long #define M(a) memset(a,0,sizeof a) #define fo(i,j,k) for(i=j;i<=k;i++) using namespace std; int n; int main() { while(1) { system("rand.exe"); system("暴力.exe"); system("hotel.exe"); if(system("fc 暴力.txt hotel.txt ")) //fc是比较文本,如果文本相同,返回1 while(1); } return 0; }
这四个程序都是要运行的,先运行前三个,最后运行对拍
双击对拍即可运行
【运行结果】
如果没有差异就是这个样子的~
有差异的话就是下面这样
有差异的话说明正解有问题,这时候根据 rand.txt 里的数据调试自己的正解程序就好啦。一开始先把rand函数里的数据造的小一点,便于调试,一直到无误以后再调试大数据。
希望可以对大家有帮助。谢谢。
相关文章推荐
- 【NOIP2011】选择客栈 乱搞
- 【noip2011】【codevs1135】选择客栈
- NOIP2011 选择客栈
- 【NOIP 2011】 选择客栈
- [NOIP2011](提高组)D1 T2 选择客栈
- #NOIP2011#选择客栈
- noip2011提高组——选择客栈
- noip2011选择客栈o(n)
- NOIP2011选择客栈
- NOIP2011 选择客栈
- 【Noip2011】选择客栈
- [Wikioi 1135][NOIP 2011提高组]选择客栈
- NOIP2011 选择客栈 解题报告(DP)
- [NOIP 2011] 选择客栈
- 【NOIP2011 Day 1】选择客栈
- NOIP2011 选择客栈
- 选择客栈 NOIP2011 提高组 Day1 T2
- Luogu P1311 [NOIp提高组2011]选择客栈
- NOIP2011 选择客栈 题解(最简方法,超短代码)
- noip 2011 选择客栈