A - Arya and Bran :水题,wa了一发。
题意:A给B糖果,每天可以给a[i]个,最多给8个,剩下的可以存下下来之后给。
求:A给Bk个糖果最少的天数(1-n)天以内才能给。
所以直接求解就好了。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define siz 100005
using namespace std;
int n,k;
int gp[siz];
void solve(){
int ans = 0;
int t;
for(int i=1;i<=n;i++){
if(gp[i]>=8){
ans+=8;
gp[i+1] += gp[i] - 8;
}
else ans += gp[i];
if(ans>=k||gp[i]==0){
cout<<i<<endl;
break;
}
}
if(ans<k){
cout<<-1<<endl;
}
}
int main()
{
while(~scanf("%d%d",&n,&k)){
for(int i=1;i<=n;i++){
scanf("%d",&gp[i]);
}
solve();
}
return 0;
}
第二题:
B - Game of the Rows 题意:
给有n行座位,每行有8个座位,12相邻,34相邻,45相邻,56相邻,78相邻。
给m个团体,每个团体有a[i]个人,不同团体的人不能坐在一块,问能否让这所有的人坐下,是输出yes,否则no。
思路:贪心:如果某个团体超过四个人,则按照4人一组坐3456,如果座位不够,再按两人一组坐12或者78,否则就无法坐下。按死人一组分完之后,剩余的人会是3,2,1三种情况。如果是3个人,尽可能先做4,个人的座位,如果座位不够则要坐两个人的位置,并且要占两个,再不够。。无法坐下。
如果是2个人,先坐2的位置,不够再坐4的位置,此时,4的位置旁边还能坐一个人的位置,所以tx++,表示还能坐一个人。再不够,则两人分开坐tx的位置,再不够。。无法坐下。如果是1个人,先坐一个人的位置tx,如果不够,坐4个人的位置,旁边可以坐2个人,所以2人位置要+1,再不够,坐两人位置。还不够。。无法坐下。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define siz 100005
#include <queue>
using namespace std;
int n,k;
int gp[siz];
priority_queue<int>que;
void solve(){
int flag = 1;
//int i=1,j=1;
int seat2 = 2*n;
int seat4 = n;
int tx = 0;
while(!que.empty()){
int x = que.top();
que.pop();
int y = x/4;
int mo = x%4;
if(seat4>=y){
seat4 -= y;
}
else{
y-=seat4;
seat4 = 0;
if(seat2>=2*y){
seat2 -= 2*y;
}
else{
flag = 0;
break;
}
}
if(mo==3){
if(seat4>0) seat4 -= 1;
else{
if(seat2>1){
seat2 -=2;
}
else{
flag = 0;
break;
}
}
}
if(mo==2){
if(seat2>0){
seat2 -=1;
}
else{
if(seat4>0){
seat4 -= 1;
tx++;
}
else if(tx>1){
tx -= 2;
}
else{
flag = 0;
break;
}
}
}
if(mo==1){
if(tx>0){
tx-=1;
}
else if(seat4>0){
seat4 -=1;
seat2 +=1;
}
else if(seat2>0){
seat2 -=1;
//seat2 +=1;
}
else{
flag =0;
break;
}
}
}
if(flag){
cout<<"YES"<<endl;
}
else{
cout<<"NO"<<endl;
}
}
int main()
{
while(~scanf("%d%d",&n,&k)){
while(!que.empty()) que.pop();
for(int i=1;i<=k;i++){
scanf("%d",&gp[i]);
que.push(gp[i]);
}
solve();
}
return 0;
}
第三题: C - Journey
给n个节点的树(m-1条边),相邻两点之间的距离是1,一人从1节点出发,不能往回走,从该节点到其他与该节点 的节点的 概率是一样的。(相当于,如果这个节点有3个节点可以走,那么走每个节点的概率就是1/3)。问:该人能走最远的距离的期望值是多少。
思路:最远当然 是到达叶子节点。所以期望E(x) = dis[a1]*p[a1]+....。就是每一个叶子节点到根节点的距离乘以概率。概率就是根节点到达上一个节点的概率乘以上个节点到这个节点的概率。深搜一遍就行了。
#include <iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#define siz 100005
const int maxn = 100000;
typedef long long LL;
using namespace std;
struct Edge
{
int to,w,next;
} edges[maxn*3];
int n,tot,q,k;
int head[maxn+5],num[maxn+5];
int d[maxn+5],cot,cnt;
double ans;
void Addedge(int x,int y,int w)
{
edges[++tot].to = y, edges[tot].w = w;
edges[tot].next = head[x], head[x] = tot;
num[x]++;
}
void dfs(int x,int fa,double y)
{
int ok = 1,nu=num[x];
if(fa!=-1) nu--;
double yy = 1.0/nu*y;
for(int i=head[x]; i!=-1; i=edges[i].next)
{
int to = edges[i].to;
if(to==fa) continue;
d[to] = d[x] + edges[i].w, ok = 0;
dfs(to,x,yy);
}
if(ok)
{
ans+=y*d[x]*1.0;
}
}
int main()
{
int x,y;
while(~scanf("%d",&n))
{
tot = 0;
for(int i=1; i<=n; i++) head[i] = -1,num[i]=0;
for(int i=1; i<n; i++)
{
scanf("%d %d",&x,&y);
Addedge(x,y,1);
Addedge(y,x,1);
}
cnt = cot = ans = 0;
d[1] = 0;
dfs(1,-1,1.0);
if(n==1) ans = 0;
printf("%.15f\n",ans);
}
return 0;
}