Codeforces Round #501 div3(C++)

A. Points in Segments

题意:一个数n和给出一些区间,输出1~n中不在这些区间的数(所有都是闭区间),由于这题数据范围很小,所以暴力就可以解决,如果需要优化,把所有区间按区间左边界从小到大排个序就行

C++代码如下(纯暴力)

#include<iostream>
using namespace std;
const int N=110;
bool st[N];//标记哪些数出现在区间里了 
int n,m,sum,ans;
int main(){
	cin>>n>>m;
	while(n--){
		int a,b;
		cin>>a>>b;
		for(int i=a;i<=b;i++)
			if(!st[i])sum++,st[i]=true;
	}
	cout<<m-sum<<endl;//输出没有出现的数的个数 
	for(int i=1;i<=m;i++)
		if(!st[i])cout<<i<<" ";
	cout<<endl;
	return 0;
}

B. Obtaining the String

题意:给定两个字符串s和t,问s能不能只通过相邻两个字母之间的交换变成t,如果可以,给出交换的序列ans[],ans[i]表示交换s[ans[i]]和s[ans[i]+1],所以只需要从前往后枚举字符串t,找出t[i]在s中出现的下标j,然后把s[j]从后往前移到下标为i的位置,同时更新序列ans

C++代码如下:

#include<iostream>
#include<vector>
using namespace std;
int main(){
	int n;
	string s,t;
	cin>>n>>s>>t;
	vector<int> ans;
	for(int i=0;i<n;i++){
		if(s[i]==t[i])continue;//如果已经相等,则不需要任何移动了,continue 
		int pos=-1;
		for(int j=i+1;j<n;j++){
			if(s[j]==t[i]){
			    pos=j;
			    break;
			}
		}
		if(pos==-1){//如果s[i]在字符串t中不存在,则直接输出-1,跳出循环 
			cout<<-1<<endl;
			return 0;
		}
		for(int j=pos-1;j>=i;j--){//从后往前把s[pos]移到下标为i的位置上
			swap(s[j],s[j+1]);
			ans.push_back(j+1);//j+1是因为题目下标从1开始,我们的字符串是从0开始 
		}
	}
	cout<<ans.size()<<endl;
	for(int i=0;i<ans.size();i++)cout<<ans[i]<<" ";
	cout<<endl;
	return 0;
}

C. Songs Compression

题意:将n首歌装入内存,n首歌的大小存入数组a[],压缩后的大小存入数组b[],内存为m,问至少压缩多少首歌才可以将所有歌曲存入内存,sum1存储a[]数组的和,sum存储b[]数组的和,先判断sum是否大于m,如果是,则输出-1;否则就将a[i]-b[i]的值存入数组c[i]中,再对c[]进行排序,然后进入循环,从后往前枚举数组c[],每次让sum1减去c[i],直到sum<=m就退出循环

C++代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
const int N=100010;
int c[N];
int n,m;
int main(){
	cin>>n>>m;
	long long sum=0,sum1=0;
	for(int i=1;i<=n;i++){
		int a,b;
		cin>>a>>b;
		sum+=b,sum1+=a;
		c[i]=a-b;
	}
	if(sum>m)cout<<-1<<endl;
	else{
		sort(c+1,c+n+1);
		int cnt=0;
		for(int i=n;sum1>m&&i>=1;i--){
			sum1-=c[i];
			cnt++;
		}
		cout<<cnt<<endl;
	}
	return 0;
}

D. Walking Between Houses

题意:一条路边有n个房子(从左到右此次为1,2,...,n),现在要求走k步,所走的距离刚好为s的方案,初始时在1号房子,有两种情况:

1、走k步不可能走过的距离为s,即走最长的路径走k遍都小于s,即(n-1)*k<s

2、走k步距离可以为s,由于房子可以重复经过,所以我们设置一个变量t,t=s/k,就是每一步走t个距离,来回走k步刚好走完了s个距离,当然不是所有的方案都可以整除,所以另外设置一个变量mod,mod=s%k,前mod步我们走t+1个距离,后面的k-mod步走t个距离就可以啦!

C++代码如下:

#include<iostream>
using namespace std;
int main(){
	int n;
	long long s,k;
	cin>>n>>k>>s;
	if(k*(n-1)<s)cout<<"NO"<<endl;
	else{
        //last记录上一次走过的房子
		int last=1,flag=1,t=s/k,mod=s%k;
        //由于不可能在一个房子呆着,所以每步的距离必须至少为1,若k>s,则不满足要求
		if(k>s)cout<<"NO"<<endl;
		else{
			cout<<"YES"<<endl;
            //由于是左右来回走,所以设置flag变量,flag=1表示往右走,flag=-1表示往左走
			for(int i=0;i<k;i++){
				if(i<mod){
					int x=last+flag*(t+1);
					cout<<x<<" ";
                    flag=-flag,last=x;//更新flag和last
				}else{
					int x=last+flag*t;
					cout<<x<<" ";
                    flag=-flag,last=x;
				}
			}
			cout<<endl;
		}
	}
	return 0;
}

E1. Stars Drawing (Easy Edition)

题意:给出一个图,只有'.'和'*'两个符号,求这些‘*’包含的星星个数,如果包含的星星可以全部覆盖所有的‘*’,则输出星星的个数及它们的信息,否则输出-1,详情见代码,有很详细的注释

C++代码如下:

#include<iostream>
using namespace std;
const int N=110,M=N*N;
char g[N][N];
bool st[N][N];
int n,m,ans,cnt;
//ans记录所有可以被星星覆盖的'*'的数量 
struct Node{
	//结构体存储能覆盖*的星星的中心和每条边的长度 
	int u,v,len;
}s[M];
void bfs(int u,int v){
	//maxx存储该星星每条边最长的长度,sum存储该星星能覆盖几个新的(即还未被其他星星覆盖的)*符号 
	int maxx=0,sum=0;
	//i枚举的是星星每条边的长度(不包括中心) 
	//由于不能超过上下左右边界,所以最长为 min(min(u-1,n-u),min(v-1,m-v))
	for(int i=1;i<=min(min(u-1,n-u),min(v-1,m-v));i++)
		if(g[u+i][v]=='*'&&g[u][v+i]=='*'&&g[u-i][v]=='*'&&g[u][v-i]=='*')//必须上下左右都是* 
			maxx++;//min是星星每条边的长度 
		else break;
	//如果可以组成星星,则标记u,v号位置已经被计算过了 
	if(maxx&&!st[u][v])st[u][v]=true,ans++;
	for(int i=1;i<=maxx;i++){
		//判断!st[][]是为了防止重复计算某个*所在的位置 
		if(!st[u+i][v])st[u+i][v]=true,ans++,t++;
		if(!st[u][v+i])st[u][v+i]=true,ans++,t++;
		if(!st[u][v-i])st[u][v-i]=true,ans++,t++;
		if(!st[u-i][v])st[u-i][v]=true,ans++,t++;
	}
	if(t)s[cnt++]={u,v,minn};//如果t不为0,则将该星星存入结构体 
}
int main(){
	cin>>n>>m;
	int sum=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			cin>>g[i][j];
			if(g[i][j]=='*')sum++;//sum标记星号'*'的个数 
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			if(g[i][j]=='*')
				bfs(i,j);
	if(sum-ans==0){//如果所有的星号'*'都可以被覆盖,则输出需要的星星数量及它们的信息 
		cout<<cnt<<endl;
		for(int i=0;i<cnt;i++)cout<<s[i].u<<" "<<s[i].v<<" "<<s[i].len<<endl;
	}else cout<<-1<<endl;
	return 0;
}

E2. Stars Drawing (Hard Edition)

题意:刚开始一看,这不是跟上面一题一模一样吗,仔细一看,数据范围改了,斗胆用上面的代码提交了一下,发现能过,就是有点慢,反正过了就行哈哈哈,N记得开成1010,110是上一题的,所以上一题是有暴力写法吗,不会哇

C++代码见上一题

F. Bracket Substring

不会写T^T,题解也看不懂,几年前的题也搜不到别的题解了......

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值