Codeforces Round#536(Div.2)
A:找到 'X' 的十字,因为不能越界,所以从2~n-1进行查找,数据规模比较小,全部遍历一遍即可
#include<cstdio>
#define MAXN 501
int a[MAXN][MAXN];
int main()
{
int n;
int ans=0;
scanf("%d",&n);
getchar();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
char c=getchar();
switch (c)
{
case 'X':a[i][j]=1;break;
case '.':a[i][j]=0;break;
default :break;
}
}
getchar();
}
for(int i=2;i<=n-1;i++)
for(int j=2;j<=n-1;j++)
{
if(a[i][j]&&a[i-1][j-1]&&a[i-1][j+1]&&a[i+1][j+1]&&a[i+1][j-1])
ans++;
}
printf("%d",ans);
return 0;
}
B:餐馆有n种菜,每种ai盘,每种花费ci,现在有m个客人,每个客人想要di盘ti种菜,根据下述规则,计算所得钱数
1.若现有菜能够满足客人需要,则当前客人吃完di盘菜,正常付款
2.若不够,则将所需菜先全部给予,然后在花费最少的菜中给,若花费相似,先给所剩盘数少的菜,正常付款
3.若给完菜客人还是得不到满足,则愤然离席,带走所有已经上的菜,并且不付钱
模拟题,待补
#include<cstdio>
#include<algorithm>
#define MAXN 100005
#define ll long long
using namespace std;
struct NOTE
{
ll a,c;
ll num;
}rst[MAXN];
bool operator <(NOTE a,NOTE b)
{
return a.c<b.c;
}
ll pos[MAXN];
ll n,m;
ll tot;
void scan()
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&rst[i].a);
for(int i=1;i<=n;i++)
scanf("%lld",&rst[i].c);
return;
}
void init()
{
tot=0;
for(int i=1;i<=n;i++)
rst[i].num=i;
for(int i=1;i<=n;i++)
tot+=rst[i].a;
sort(rst+1,rst+1+n);
for(int i=1;i<=n;i++)
{
pos[rst[i].num]=i;
}
return;
}
void solve()
{
int find=1;
for(int i=1;i<=m;i++)
{
ll need,num;
ll res=0;
scanf("%lld%lld",&need,&num);
if(num>tot)
{
tot=0;
printf("0\n");
continue;
}
int posi=pos[need];
if(rst[posi].a>=num)
{
res+=num*rst[posi].c;
rst[posi].a-=num;
tot-=num;
num=0;
}
else
{
res+=rst[posi].a*rst[posi].c;
tot-=rst[posi].a;
num-=rst[posi].a;
rst[posi].a=0;
while(num!=0)
{
//printf("%d ",find);
while(rst[find].a==0&&find<=n)
{
find++;
}
// printf("cost:%d ",rst[find].c);
if(find>n)
{
tot=0;
res=0;
break;
}
if(rst[find].a>=num)
{
res+=num*rst[find].c;
rst[find].a-=num;
tot-=num;
num=0;
}
else
{
res+=rst[find].a*rst[find].c;
tot-=rst[find].a;
num-=rst[find].a;
rst[find].a=0;
}
}
}
printf("%lld\n",res);
}
}
int main()
{
scan();
init();
solve();
return 0;
}
C:给n个数,分成m组,求每组和的平方的最小数
通过样例和直觉,两个数字在一起的情况值最小,得到的数也最小,所以结果最小,只需要把最小数和最大数依次相加求结果即可(算是一种贪心?
#include<cstdio>
#include<algorithm>
#define MAXN 300005
#define ll long long
using namespace std;
int a[MAXN];
int main()
{
int n;
ll ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
sort(a+1,a+1+n);
for(int i=1;i<=n/2;i++)
{
int num=a[i]+a[n+1-i];
ans+=num*num;
}
printf("%lld",ans);
return 0;
}
D:n个点,m条路径,从任意点开始访问,访问后记录路径,求字典序最小的遍历
讲真最开始没有想到应该怎么做,写了个很鬼畜的搜索,然后样例过了,卡住了,又想了想。
关键在于访问一个节点结束之后,人可以回到之前经过的节点,再去访问其余节点,所以最小并没有一搜到底。
每次将未访问的节点放入一个集合中,从中挑选出最小的,从这个节点出发将所有能够访问的节点添加进集合中,然后将这个点移出集合,标记这个节点使它不会被再次加入到集合当中。
易得,从1开始寻找可访问节点。
用到了链式前向星和set的操作(set真香)
#include<cstdio>
#include<algorithm>
#include<set>
#define MAXN 200005
using namespace std;
int nt[MAXN],st[MAXN],to[MAXN];
int top,cnt=1;
int n,m,flag;
set<int> sta;
int book[MAXN],ans[MAXN];
void add(int x,int y)
{
top++;to[top]=y;nt[top]=st[x];st[x]=top;
}
void DFS(int pos)
{
printf("%d ",pos);
book[pos]=1;
sta.erase(pos);
if(cnt==n)
{
flag=1;
return;
}
while(!flag)
{
int siz=sta.size();
for(int i=st[pos];i;i=nt[i])
{
int num=to[i];
if(book[num]==0)
sta.insert(num);
}
set<int>::iterator it=sta.begin();
cnt++;
DFS(*it);
}
return;
}
int main()
{
int cnt=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
DFS(1);
return 0;
}
E:待补
F:待补