第29次CCF计算机软件能力认证 1&2题

1.田地丈量

问题描述

西西艾弗岛上散落着 n 块田地。每块田地可视为平面直角坐标系下的一块矩形区域,由左下角坐标 (x1,y1) 和右上角坐标 (x2,y2) 唯一确定,且满足 x1<x2、y1<y2。这 n 块田地中,任意两块的交集面积均为 0,仅边界处可能有所重叠。

最近,顿顿想要在南山脚下开垦出一块面积为 a×b 矩形田地,其左下角坐标为 (0,0)、右上角坐标为 (a,b)。试计算顿顿选定区域内已经存在的田地面积。

输入格式

从标准输入读入数据。

输入共 n+1 行。

输入的第一行包含空格分隔的三个正整数 n、a 和 b,分别表示西西艾弗岛上田地块数和顿顿选定区域的右上角坐标。

接下来 n 行,每行包含空格分隔的四个整数 x1、y1、x2 和 y2,表示一块田地的位置。

输出格式

输出到标准输出。

输出一个整数,表示顿顿选定区域内的田地面积。

#include<bits/stdc++.h>
using namespace std;

int main(){
	int n,a,b;
	cin>>n>>a>>b;
	int i=0;
//左下角和右上角的坐标
	int x1,y1,x2,y2;
//mj表示面积
	int mj=0;
	int x3,y3,x4,y4;
	for(i=1;i<=n;i++){
		cin>>x1>>y1>>x2>>y2;
		if(y1>=b){
			mj+=0;
		}
		if(y1<b){
			if(x1>=a){
				mj+=0; 
			}
			else if(x1<a){
				x3=max(x1,0);
				y3=max(y1,0);
				x4=min(x2,a);x4=max(0,x4);
				y4=min(y2,b);y4=max(0,y4);
				mj+=(x4-x3)*(y4-y3);
			}
		}
	}
	cout<<mj;
	return 0;
} 

2.垦田计划

问题描述

顿顿总共选中了 n 块区域准备开垦田地,由于各块区域大小不一,开垦所需时间也不尽相同。据估算,其中第 i 块(1≤i≤n)区域的开垦耗时为 ti 天。这 n 块区域可以同时开垦,所以总耗时 tTotal 取决于耗时最长的区域,即:tTotal=max{t1,t2,⋯,tn}

为了加快开垦进度,顿顿准备在部分区域投入额外资源来缩短开垦时间。具体来说:

  • 在第 i 块区域投入 ci 单位资源,便可将其开垦耗时缩短 1 天;

  • 耗时缩短天数以整数记,即第 i 块区域投入资源数量必须是 ci 的整数倍;

  • 在第 i 块区域最多可投入 ci×(ti−k) 单位资源,将其开垦耗时缩短为 k 天;

  • 这里的 k 表示开垦一块区域的最少天数,满足 0<k≤min{t1,t2,⋯,tn};换言之,如果无限制地投入资源,所有区域都可以用 k 天完成开垦。

现在顿顿手中共有 m 单位资源可供使用,试计算开垦 n 块区域最少需要多少天?

输入格式

从标准输入读入数据。

输入共 n+1 行。

输入的第一行包含空格分隔的三个正整数 n、m 和 k,分别表示待开垦的区域总数、顿顿手上的资源数量和每块区域的最少开垦天数。

接下来 n 行,每行包含空格分隔的两个正整数 ti 和 ci,分别表示第 i 块区域开垦耗时和将耗时缩短 1 天所需资源数量。

输出格式

输出到标准输出。

输出一个整数,表示开垦 n 块区域的最少耗时。

二分查找进行优化

#include<bits/stdc++.h>
using namespace std;
//stl
typedef pair<int,int> pit;
const int maxn=100010;
pit land[maxn];
int n,m,k;
int m1=m;
//从小到大排序需要用到的参数函数
bool cmp(pit l1,pit l2)
{
	return l1.first<l2.first;
}
//判断当前天数是否合规 
dcs(int day){
	int i=0;
	m1=m;
	for(i=n-1;i>=0;i--){
		if(land[i].first>day){
			m1-=(land[i].first-day)*land[i].second;
		}
	} 
	if(m1==0)  return 0;
	if(m1<0) return -1;
	if(m1>0) return 1;
}
//二分查找
int binsch(){
	int low=k,high=land[n-1].first;
	int mid;
	int mind=land[n-1].first;
	while(low<=high){
		mid=(low+high)>>1;
		if (dcs(mid)==0){
			return mid;
		}
		else if(dcs(mid)<0){
			low=mid+1;
		}
		else if(dcs(mid)>0){
			mind=min(mind,mid);
			high=mid-1;
		}
	}
	return mind;
}
int main(){
	scanf("%d%d%d",&n,&m,&k);
	int i=0;
	for(i=0;i<n;i++){
		cin>>land[i].first>>land[i].second;
	}
	sort(land,land+n,cmp);
	cout<<binsch()<<endl;
	return 0;
} 

暴力解题(70分)

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000010;
int n,m,k;
typedef struct{
	int t;
	int c;
}tiandi;
tiandi td[maxn];
int ts;
//排序
void maopao(tiandi *td){
	int i=0;
	int j=0,temp=0;
	for(i=1;i<=n;i++){
		for(j=1;j<=n-i;j++){
			if(td[j].t <td[j+1].t){
				temp=td[j].t;
				td[j].t=td[j+1].t;
				td[j+1].t=temp;
				temp=td[j].c;
				td[j].c=td[j+1].c;
				td[j+1].c=temp;
			}
		}
	}
}
int main(){
	cin>>n>>m>>k;
	int i=0;
	for(i=1;i<=n;i++){
		cin>>td[i].t >>td[i].c ;
	}
	maopao(td);
	ts=td[1].t ;
//每次减1
	while(td[1].t >k && m>0){
		int j=0;
		for(j=1;j<=n && td[j].t ==ts;j++){
			td[j].t --;
			m-=td[j].c ;
		}
		ts--;
	}
	if(m<0){
		cout<<ts+1<<endl;
	}
	else{
		cout<<ts<<endl;
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值