清橙OJ A1191. 选择客栈

题目来源:http://www.tsinsen.com/A1191

A1191. 选择客栈

时间限制:1.0s   内存限制:128.0MB  

试题来源

NOIP2011 提高组

问题描述

  丽江河边有 n 家很有特色的客栈,客栈按照其位置顺序从1 n 编号。每家客栈都按照某一种色调进行装饰(总共k 种,用整数0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费。
  两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中。晚上,他们打算选择一家咖啡店喝咖啡,要求咖啡店位于两人住的两家客栈之间(包括他们住的客栈),且咖啡店的最低消费不超过p
  他们想知道总共有多少种选择住宿的方案,保证晚上可以找到一家最低消费不超过p元的咖啡店小聚。

输入格式

  输入共n+1 行。
  第一行三个整数 nkp,每两个整数之间用一个空格隔开,分别表示客栈的个数,色调的数目和能接受的最低消费的最高值;
  接下来的 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,0000<k≤500≤p≤100 0≤最低消费≤100

-----------------------------------------------------

解题思路

数学题

由于题目只要求解住宿方案个数,不用求住宿方案+咖啡厅碰面方案个数,所以枚举客栈个数。两个客栈一左一右,考虑边读取输入边计算,枚举右边的客栈。

记最低消费不超过p的咖啡厅为“便宜咖啡厅”,记总的住宿方案个数为ans。算法如下:

1. 对于每一个读入的客栈,如果有便宜的咖啡厅,则该客栈左边所有客栈都能住,即ans+=c1[c]

2. 若没有便宜的咖啡厅,则只有该客栈左侧最靠右的有便宜咖啡厅的客栈左侧(包括其自身)的客栈可选,即ans+=c2[c]

3. 维护两个长度为k的数组c1[k]c2[k]. 每次读入一个颜色为c的客栈,c1[c]++4. 若该读入的客栈有便宜咖啡厅,则将c1k个值复制给c2

-----------------------------------------------------

代码

//A1191. 选择客栈

#include<iostream>
#include<fstream>
using namespace std;

const int N_MAX = 200005;
const int K_MAX = 55;
int c1[K_MAX] = {};							// 0~(i-1)中色调=k的客栈数	
int c2[K_MAX] = {};							// 0~last中色调=k的客栈数	

int main()
{
#ifndef ONLINE_JUDGE
	ifstream fin("A1191.txt");
	int n,k,p,i,j,price,c;
	fin >> n >> k >> p;
	int last = -1;							// 当前最后一个消费小于等于p的咖啡店
	long long ans = 0;
	for (i=0; i<n; i++)
	{
		fin >> c >> price;
		if (price<=p)
		{
			last = i;						// 最后一个消费小于等于p的咖啡店
		}
		if (i==last)						// 如果右侧客栈自带便宜的咖啡馆
		{
			ans += c1[c];					// 则所有左侧的客栈都可以选择
		}
		else								// 若右侧客栈没有便宜的咖啡馆
		{
			ans += c2[c];					// 则只有右侧客栈左侧最靠右的便宜咖啡馆左侧(包括其自身)的客栈可选
		}


		c1[c]++;
		if (i==last)
		{
			for (j=0; j<k; j++)
			{
				c2[j] = c1[j];
			}

		}

	}
	fin.close();
	cout << ans;
	return 0;
#endif
#ifdef ONLINE_JUDGE
	int n,k,p,i,j,price,c;
	cin >> n >> k >> p;
	int last = -1;							// 当前最后一个消费小于等于p的咖啡店
	long long ans = 0;
	for (i=0; i<n; i++)
	{
		cin >> c >> price;
		if (price<=p)
		{
			last = i;						// 最后一个消费小于等于p的咖啡店
		}
		if (i==last)						// 如果右侧客栈自带便宜的咖啡馆
		{
			ans += c1[c];					// 则所有左侧的客栈都可以选择
		}
		else								// 若右侧客栈没有便宜的咖啡馆
		{
			ans += c2[c];					// 则只有右侧客栈左侧最靠右的便宜咖啡馆左侧(包括其自身)的客栈可选
		}


		c1[c]++;
		if (i==last)
		{
			for (j=0; j<k; j++)
			{
				c2[j] = c1[j];
			}

		}

	}
	cout << ans;
	return 0;
#endif
}

猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/80566900