Codeforces Round #501
Problem A.Points in Segments
题目概述
给定Ox轴总长度N和线段个数M,并分别给出M个线段所在的区间[l,r]覆盖在Ox轴上,问在轴上还有几个点没有被覆盖并将其罗列出来。数据规模N,M均小于100.
思路:
一个类似于桶排序的思想,用bool数组去做覆盖,模拟这个过程,最后统计并输出即可。
代码A:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int i,j,n,m,b[1001];
int r()
{
int ans=0;
char ch=getchar();
while(ch<'0'||ch>'9')
{
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
ans*=10;
ans+=ch-'0';
ch=getchar();
}
return ans;
}
int x,y;
int main()
{
n=r(),m=r();
for(i=1;i<=n;i++)
{
x=r(),y=r();
for(j=x;j<=y;j++)
b[j]=1;
}
int sum=0;
for(i=1;i<=m;i++)
if(!b[i])
sum++;
cout<<sum<<endl;
for(i=1;i<=m;i++)
if(!b[i])
cout<<i<<" ";
return 0;
}
Problem B.Obtaining the String
题目概述
给定两个长度为N(N<=50)的小写字母组成的字符串S,T,可以将S字符串中相邻的ai与ai+1两位互换,求一种可行的互换方式,使得S变为T,若不能则输出-1,若能则输出互换的步数和题干中所描述的“ai与ai+1两位互换”的i。要求总步数不超过10000.
思路:
贪心思想。直接从前往后搜,若Si=Ti则继续向后搜,反之则从S中找到使得Sj=Ti的j,并将Sj转移到Si的位置上,转移时想着记录操作。由于数据规模不大,时间复杂度为ON2,所以可行。
代码B:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
using namespace std;
int i,j,n,m;
int c[10001];
char a[51],b[51];
int r()
{
int ans=0;
char ch=getchar();
while(ch<'0'||ch>'9')
{
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
ans*=10;
ans+=ch-'0';
ch=getchar();
}
return ans;
}
int main()
{
n=r();
for(i=1;i<=n;i++)
cin>>a[i];
for(i=1;i<=n;i++)
cin>>b[i];
int j=1,swi=0;
char x;
while(j<=n)
{
for(i=j;i<=n;i++)
if(a[i]==b[j])
{
for(int k=i;k>j;k--)
{
x=a[k];
a[k]=a[k-1];
a[k-1]=x;
c[++m]=k-1;
}
swi=1;
break;
}
if(!swi)
{
cout<<-1;
return 0;
}
j++;swi=0;
}
cout<<m<<endl;
for(i=1;i<=m;i++)
cout<<c[i]<<" ";
return 0;
}
Problem C.Songs Compression
题目概述
给定N个音乐的原大小和压缩后的大小,现在有一个容量为M的闪存器,需要我们选取几个音乐进行压缩,使得这N个音乐完全被容纳在闪存器中。题目要求压缩的音乐数量尽可能的小,输出最小的个数。
思路:
个人认为比B题简单的贪心,实际上就是把我们现在欠下的容量用压缩掉的体积补回来,所以思路就是对每一个音乐作差,然后排序,让压缩体积大的尽可能的先压缩,之后模拟这个压缩过程直至满足题意,输出个数,如果全部压缩之后仍然不行,则输出-1。
代码C:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
long long i,j,n,m;
struct data
{
long long x,y,w;
}a[100001];
long long r()
{
long long ans=0;
char ch=getchar();
while(ch<'0'||ch>'9')
{
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
ans*=10;
ans+=ch-'0';
ch=getchar();
}
return ans;
}
long long cmp(data aa,data bb)
{
if(aa.w>bb.w) return 1;
return 0;
}
long long sum,sum1;
int main()
{
n=r(),m=r();
for(i=1;i<=n;i++)
{
a[i].x=r(),a[i].y=r();
a[i].w=a[i].x-a[i].y;
sum+=a[i].y;
sum1+=a[i].x;
}
if(sum>m)
{cout<<-1;
return 0;}
sum1-=m;
if(sum1<=0)
{cout<<0;
return 0;}
long long tot=0;
sort(a+1,a+n+1,cmp);
for(i=1;i<=n;i++)
{
sum1-=a[i].w;
tot++;
if(sum1<=0)
{cout<<tot;return 0;}
}
}
/*
4 14
5 5
4 4
3 3
3 2
*/
Problem D.Walking Between Houses
题目概述
给定一个长度为N的线段,从1出发,不能超过[1,N]的范围,要求在K步以内走完S的距离,每一步的距离即为出发点和结束点的坐标差的绝对值。输出是否能够完成要求,若不能,输出NO,反之输出YES并且输出从第二步开始的坐标。
思路:
一个模拟题,我们可以先尽全力的走,然后一次一步的走。m*(n-1) < s||m > s即为每次都尽全力还走不完和每次只走1步都会超过S的情况。
代码D:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
unsigned long long i,j,n,m,s;
unsigned long long r()
{
unsigned long long ans=0;
char ch=getchar();
while(ch<'0'||ch>'9')
{
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
ans*=10;
ans+=ch-'0';
ch=getchar();
}
return ans;
}
int main()
{
n=r(),m=r(),s=r();
if(m*(n-1)<s||m>s)
{
cout<<"NO";
return 0;
}
cout<<"YES"<<endl;
unsigned long long now=1;
unsigned long long mm=m;
for(i=1;i<=mm;i++)
{
if(now-1>n-now)
{
if(now-1>s-m+1)
now-=s-m+1,s-=s-m+1;
else
s-=now-1,now=1;
}
else
{
if(n-now>s-m+1)
now+=s-m+1,s-=s-m+1;
else
s-=n-now,now=n;
}
cout<<now<<" ";
m--;
}
return 0;
}
/*
10 5 6
*/
Problem E1. Stars Drawing (Easy Edition)
题目概述
给定一个N * M的网格,每个格子里为“ * “或” . “,以一个“ * ”为中心向四周均匀发散,四边各发散1个格子组成的十字架形状记为半径为1,以此类推。十字架之间可以重合、有交叉。某张N * M的网格可能是由多个十字架组成,问这个网格能否由多个十字架组成,若能,则输出所有十字架中心的横坐标、纵坐标、半径。N<=100
思路:
暴力做法,找出每个能扩展出一个半径的十字架的中心点,并继续向外扩展,并标记上已经扩展过的点。最后检查为 * 但是没有标记的点,如果存在则输出-1,反之正常输出即可。
代码D:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
int i,j,n,m;
int a[101][101];
int b[101][101],ans[10000][3];
char xx;
int r()
{
int ans=0;
char ch=getchar();
while(ch<'0'||ch>'9')
{
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
ans*=10;
ans+=ch-'0';
ch=getchar();
}
return ans;
}
int tot;
void dfs(int x,int y,int s)
{
if(s+x<=n&&x-s>0&&a[s+x][y]&&a[x-s][y]
&&s+y<=m&&y-s>0&&a[x][y+s]&&a[x][y-s])
b[s+x][y]=b[x-s][y]=b[x][s+y]=b[x][y-s]=0,
dfs(x,y,s+1);
else
ans[++tot][0]=x,ans[tot][1]=y,ans[tot][2]=s-1;
}
int kk;
int main()
{
n=r(),m=r();
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
xx=getchar();
if(xx=='*')
a[i][j]=b[i][j]=1,kk=1;
}
getchar();
}
if(!kk)
{
cout<<0;
return 0;
}
for(i=2;i<n;i++)
for(j=2;j<m;j++)
{
if(a[i][j]&&a[i-1][j]&&a[i+1][j]&&
a[i][j+1]&&a[i][j-1])
b[i][j]=b[i-1][j]=b[i+1][j]=b[i][j+1]=b[i][j-1]=0,dfs(i,j,2);
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if(b[i][j])
{cout<<-1;
return 0;}
}
cout<<tot<<endl;
for(i=1;i<=tot;i++)
cout<<ans[i][0]<<" "<<ans[i][1]<<" "<<ans[i][2]<<endl;
return 0;
}
/*
6 8
....*...
...**...
..*****.
...**...
....*...
........
*/