http://www.tsinsen.com/ViewGProblem.page?gpid=A1191
试题来源
NOIP2011 提高组
问题描述
丽江河边有 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
数据规模和约定
对于 30%的数据,有n≤100;
对于 50%的数据,有n≤1,000;
对于 100%的数据,有2≤n≤200,000,0<k≤50,0≤p≤100, 0≤最低消费≤100。
方法1,真实过程模拟
#include<vector>
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int n,k,p;
cin>>n>>k>>p;
int a[200000][2];
for(int i=0; i<n; i++)
{
cin>>a[i][0];
cin>>a[i][1];
}
int kk=0,allsum=0;;
for(int i=0; i<k; i++)
{
kk=i;
vector<int> lz;
int count=0,j;
int inced=0;
for(j=0; j<n; j++)
{
if(a[j][0]==kk)
{
lz.push_back(0);
if(a[j][1]<=p) count++;
break;
}
}
for(j=j+1; j<n; j++)
{
if(a[j][0]==kk)
{
if(a[j][1]<=p) count++;
if(count>0)
{
lz.push_back(lz.size());//注意这里,如果和前一个之间有咖啡,那么就和前面的每一个都合法
count=0;
} else
lz.push_back(lz[lz.size()-1]); //注意这里,如果和前一个之间没有咖啡,那么就三和上一个相同
if(a[j][1]<=p) count++;
} else
{
if(a[j][1]<=p) count++;
}
}
int t=lz.size();
//cout<<kk<<"-----------"<<endl;
for(j=0; j<t; j++)
{ //cout<<lz[j]<<endl;
allsum+=lz[j];
}
}
cout<<allsum<<endl;
}
复杂性为n*k;
另外一个是n*n的,容易理解,超时间
#include <iostream>
using namespace std;
typedef struct s_hotel {
int color;
int cost;
} Hotel;
Hotel hotels[200000];
int main()
{
int n, k, p;
int i, j, s, total;
cin >> n >> k >> p;
for (i = 0; i < n; i++)
cin >> hotels[i].color >> hotels[i].cost;
total = 0;
for (i = 0; i < n; i++)
for (j = i + 1; j < n; j++)
if (hotels[i].color == hotels[j].color)
{
for (s = i; s <= j; s++)
if(hotels[s].cost <= p)
{
total++;
break;
}
}
cout << total << endl;
return 0;
}