CCF CSP 认证 2014-09

T1

问题描述

试题编号:201409-1
试题名称:相邻数对
时间限制:1.0s
内存限制:256.0MB
问题描述:

问题描述

  给定n个不同的整数,问这些数中有多少对整数,它们的值正好相差1。

输入格式

  输入的第一行包含一个整数n,表示给定整数的个数。
  第二行包含所给定的n个整数。

输出格式

  输出一个整数,表示值正好相差1的数对的个数。

样例输入

6
10 2 6 3 7 8

样例输出

3

样例说明

  值正好相差1的数对包括(2, 3), (6, 7), (7, 8)。

评测用例规模与约定

  1<=n<=1000,给定的整数为不超过10000的非负整数。

思路:直接对数组排序,然后按照题意求出差值为1的个数,这边由于数据区间比数据个数要大,因此使用标记数组统计个数再遍历区间可能更耗时。

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010;
int Arr[N];
int main(){
	int i,n,ans=0;
	cin>>n;
	for(i=1;i<=n;++i){
		cin>>Arr[i];
	}
	sort(Arr+1,Arr+1+n);
	for(i=2;i<=n;++i){
		if(Arr[i]-Arr[i-1]==1)++ans;
	}
	cout<<ans;
	return 0;
} 

T2

问题描述

试题编号:201409-2
试题名称:画图
时间限制:1.0s
内存限制:256.0MB
问题描述:

问题描述

  在一个定义了直角坐标系的纸上,画一个(x1,y1)到(x2,y2)的矩形指将横坐标范围从x1到x2,纵坐标范围从y1到y2之间的区域涂上颜色。
  下图给出了一个画了两个矩形的例子。第一个矩形是(1,1) 到(4, 4),用绿色和紫色表示。第二个矩形是(2, 3)到(6, 5),用蓝色和紫色表示。图中,一共有15个单位的面积被涂上颜色,其中紫色部分被涂了两次,但在计算面积时只计算一次。在实际的涂色过程中,所有的矩形都涂成统一的颜色,图中显示不同颜色仅为说明方便。

       
  给出所有要画的矩形,请问总共有多少个单位的面积被涂上颜色。

输入格式

  输入的第一行包含一个整数n,表示要画的矩形的个数。
  接下来n行,每行4个非负整数,分别表示要画的矩形的左下角的横坐标与纵坐标,以及右上角的横坐标与纵坐标。

输出格式

  输出一个整数,表示有多少个单位的面积被涂上颜色。

样例输入

2
1 1 4 4
2 3 6 5

样例输出

15

评测用例规模与约定

  1<=n<=100,0<=横坐标、纵坐标<=100。

思路:由于这题输入量不大,因此可以直接模拟涂色,使用bool数组来标记是否被上色,便于去重。数据量大的情况下可以使用扫描线的方式进行维护。

#include<iostream>
using namespace std;
const int N=110;
bool visited[N][N];
int main(){
	int n,lx,ly,rx,ry,i,j,ans=0;
	cin>>n;
	while(n--){
		cin>>lx>>ly>>rx>>ry;
		for(i=lx;i<rx;++i){
			for(j=ly;j<ry;++j){
				if(!visited[i][j]){
					visited[i][j]=true;
					++ans;
				}
			}
		}
	}
	cout<<ans;
	return 0;
} 

T3

问题描述

试题编号:201409-3
试题名称:字符串匹配
时间限制:1.0s
内存限制:256.0MB
问题描述:

问题描述

  给出一个字符串和多行文字,在这些文字中找到字符串出现的那些行。你的程序还需支持大小写敏感选项:当选项打开时,表示同一个字母的大写和小写看作不同的字符;当选项关闭时,表示同一个字母的大写和小写看作相同的字符。

输入格式

  输入的第一行包含一个字符串S,由大小写英文字母组成。
  第二行包含一个数字,表示大小写敏感的选项,当数字为0时表示大小写不敏感,当数字为1时表示大小写敏感。
  第三行包含一个整数n,表示给出的文字的行数。
  接下来n行,每行包含一个字符串,字符串由大小写英文字母组成,不含空格和其他字符。

输出格式

  输出多行,每行包含一个字符串,按出现的顺序依次给出那些包含了字符串S的行。

样例输入

Hello
1
5
HelloWorld
HiHiHelloHiHi
GrepIsAGreatTool
HELLO
HELLOisNOTHello

样例输出

HelloWorld
HiHiHelloHiHi
HELLOisNOTHello

样例说明

  在上面的样例中,第四个字符串虽然也是Hello,但是大小写不正确。如果将输入的第二行改为0,则第四个字符串应该输出。

评测用例规模与约定

  1<=n<=100,每个字符串的长度不超过100。

思路:本体数据量也不大,直接模拟。至于子串搜素方法,可以使用暴力BF即代码中的string.find(),也可以尝试KMP、改进KMP、BM匹配算法。

#include<iostream>
#include<string>
#include<algorithm>
#include<cctype>
using namespace std;
int main(){
	int caseSensitive,n;
	string sub,str,temp;
	cin>>sub>>caseSensitive>>n;
	if(!caseSensitive)transform(sub.begin(),sub.end(),sub.begin(),::tolower);
	while(n--){
		cin>>str;
		temp=str;
		if(!caseSensitive)transform(str.begin(),str.end(),str.begin(),::tolower);
		if(str.find(sub,0)!=-1)cout<<temp<<endl;
	}
	return 0;
}

T4

问题描述

试题编号:201409-4
试题名称:最优配餐
时间限制:1.0s
内存限制:256.0MB
问题描述:

问题描述

  栋栋最近开了一家餐饮连锁店,提供外卖服务。随着连锁店越来越多,怎么合理的给客户送餐成为了一个急需解决的问题。
  栋栋的连锁店所在的区域可以看成是一个n×n的方格图(如下图所示),方格的格点上的位置上可能包含栋栋的分店(绿色标注)或者客户(蓝色标注),有一些格点是不能经过的(红色标注)。
  方格图中的线表示可以行走的道路,相邻两个格点的距离为1。栋栋要送餐必须走可以行走的道路,而且不能经过红色标注的点。
       
  送餐的主要成本体现在路上所花的时间,每一份餐每走一个单位的距离需要花费1块钱。每个客户的需求都可以由栋栋的任意分店配送,每个分店没有配送总量的限制。
  现在你得到了栋栋的客户的需求,请问在最优的送餐方式下,送这些餐需要花费多大的成本。

 

输入格式

  输入的第一行包含四个整数n, m, k, d,分别表示方格图的大小、栋栋的分店数量、客户的数量,以及不能经过的点的数量。
  接下来m行,每行两个整数xi, yi,表示栋栋的一个分店在方格图中的横坐标和纵坐标。
  接下来k行,每行三个整数xi, yi, ci,分别表示每个客户在方格图中的横坐标、纵坐标和订餐的量。(注意,可能有多个客户在方格图中的同一个位置)
  接下来d行,每行两个整数,分别表示每个不能经过的点的横坐标和纵坐标。

输出格式

  输出一个整数,表示最优送餐方式下所需要花费的成本。

样例输入

10 2 3 3
1 1
8 8
1 5 1
2 3 3
6 7 2
1 2
2 2
6 8

样例输出

29

评测用例规模与约定

  前30%的评测用例满足:1<=n <=20。
  前60%的评测用例满足:1<=n<=100。
  所有评测用例都满足:1<=n<=1000,1<=m, k, d<=n^2。可能有多个客户在同一个格点上。每个客户的订餐量不超过1000,每个客户所需要的餐都能被送到。

思路:这题实际上就是一个最短路问题,由于路径的边权全部一致,因此可以直接用BFS来解。实际上本题可以从多个店铺出发对整幅图进行BFS,第一个遍历到客户位置的路径是一定最短的(可能有多条路径到达该位置且长度一致,但是不影响这个值是最短的),直接统计路径和即可。

#include<iostream>
#include<queue>
using namespace std;
const int N=1010;
bool visited[N][N];
int sum[N][N];
struct Point{
	int x,y,dis;
}; 
queue<Point> que;

int main(){
	int n,m,k,d,i,x,y,c,dis;
	long long ans=0;
	cin>>n>>m>>k>>d;
	for(i=1;i<=m;++i){
		cin>>x>>y;
		que.push(Point{x,y,0});
		visited[x][y]=1;
	}
	for(i=1;i<=k;++i){
		cin>>x>>y>>c;
		sum[x][y]+=c;
	}
	for(i=1;i<=d;++i){
		cin>>x>>y;
		visited[x][y]=1;
	}
	Point temp;
	while(!que.empty()){
		temp=que.front();
		que.pop();
		x=temp.x,y=temp.y,dis=temp.dis;
		if(sum[x][y])ans+=sum[x][y]*dis;
		
		
		if(x-1>=1&&visited[x-1][y]!=1){
			visited[x-1][y]=1;
			que.push(Point{x-1,y,dis+1});
		}
		
		if(x+1<=n&&visited[x+1][y]!=1){
			visited[x+1][y]=1;
			que.push(Point{x+1,y,dis+1});
		}
		
		if(y-1>=1&&visited[x][y-1]!=1){
			visited[x][y-1]=1;
			que.push(Point{x,y-1,dis+1});
		}
		
		if(y+1<=n&&visited[x][y+1]!=1){
			visited[x][y+1]=1;
			que.push(Point{x,y+1,dis+1});
		}
	}
	cout<<ans;
}

T5

问题描述

试题编号:201409-5
试题名称:拼图
时间限制:3.0s
内存限制:256.0MB
问题描述:

问题描述

  给出一个n×m的方格图,现在要用如下L型的积木拼到这个图中,使得方格图正好被拼满,请问总共有多少种拼法。其中,方格图的每一个方格正好能放积木中的一块。积木可以任意旋转。

         

输入格式

  输入的第一行包含两个整数n, m,表示方格图的大小。

输出格式

  输出一行,表示可以放的方案数,由于方案数可能很多,所以请输出方案数除以1,000,000,007的余数。

样例输入

6 2

样例输出

4

样例说明

  四种拼法如下图所示:

         

评测用例规模与约定

  在评测时将使用10个评测用例对你的程序进行评测。
  评测用例1和2满足:1<=n<=30,m=2。
  评测用例3和4满足:1<=n, m<=6。
  评测用例5满足:1<=n<=100,1<=m<=6。
  评测用例6和7满足:1<=n<=1000,1<=m<=6。
  评测用例8、9和10满足:1<=n<=10^15,1<=m<=7。

思路:还没有好的思路。。。。。。

#include<iostream>
using namespace std;
typedef long long ll;
const ll Mod=1000000007;

ll dp[1010][10];

int main(){
	int n,m,i,j;
	cin>>n>>m;
	dp[0][2]=dp[0][3]=dp[2][0]=dp[3][0]=1;
	for(i=2;i<=m;i+=2)dp[3][i]=dp[3][i-2]*2%Mod;//3行i(i%2==0)列矩阵构成的情况 
	for(i=3;i<=m;i+=3)dp[2][i]=dp[2][i-3]*2%Mod;//2行i(i%3==0)列
	for(i=2;i<=n;i+=2)dp[i][3]=dp[i-2][3]*2%Mod;//i(i%2==0)行3列
	for(i=3;i<=n;i+=3)dp[i][2]=dp[i-3][2]*2%Mod;//i(i%3==0)行2列 
	for(i=4;i<=n;++i){
		for(j=4;j<=m;++j){
			dp[i][j]=(dp[i-2][j]*dp[2][j]%Mod+dp[i-3][j]*dp[3][j]%Mod+dp[i][j-2]*dp[i][2]%Mod+dp[i][j-3]*dp[i][3]%Mod)%Mod;
		}
	}
	cout<<dp[n][m];
	return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值