您的位置:首页 > 其它

20161102的考试】模拟,树的直径,推公式……三道水题然而浪飞了……

2016-11-02 16:00 246 查看
…………喵的……今天太浪了23333

三道题都会三道都GG【滚走

…………喵的…………在AK场没上百是怎样的体验*2

T1自信不对拍,然后发现好像自己naive了;

T2……喵的我fread开小了于是RE【智障脸

T3………………题意理解错*1,瞬间心态爆炸GGGGGGGG

T1:

题面:模拟一下连连看,找每个块有多少能和它消除的

思路:……模拟啊模拟,喵哒似乎是状态稍微记少了一点,反正是水题随便写写就能过的,比起dfs果然还是bfs比较好看

代码:

#include<bits/stdc++.h>
#define MAXN 36
#define INF 0x3f3f3f3f
#define push(a,b,c) que[tail++]=a,que[tail++]=b,que[tail++]=c
using namespace std; int n,m;
const int cx[4] = {-1,0,1,0};
const int cy[4] = {0,1,0,-1};

int gph[MAXN][MAXN];
int cnt[MAXN][MAXN];

const int MAXQ = MAXN*MAXN*12;
int que[MAXQ],head,tail;

int dis[MAXN][MAXN][4];

inline void bfs(int x,int y){
if(!gph[x][y]) return ;
int x0=x,y0=y;
memset(dis,INF,sizeof dis);
head=tail=0;
for(int dir=0;dir<4;++dir)
dis[x][y][dir]=0,push(x,y,dir);

int pre_dir;
while(head^tail){
x=que[head++],y=que[head++],pre_dir=que[head++];
if(head==MAXQ) head=0;

if(dis[x][y][pre_dir]>=3) continue;

for(int dir=0;dir<4;++dir){
int xx=x+cx[dir],yy=y+cy[dir];
if(xx<0||xx>n+1||yy<0||yy>m+1) continue;
for(int dir2=0;dir2<4;++dir2){
if(dis[xx][yy][dir2] > dis[x][y][pre_dir]+((pre_dir^dir)&1)+((dir^dir2)&1)){
dis[xx][yy][dir2] = dis[x][y][pre_dir]+((pre_dir^dir)&1)+((dir^dir2)&1);
if(!gph[xx][yy]){
push(xx,yy,dir2);
if(tail==MAXQ) tail=0;
}
}
}
}
}

for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if((i^x0)||(j^y0))
if(gph[i][j]==gph[x0][y0]&&(dis[i][j][0]<3||dis[i][j][1]<3||dis[i][j][2]<3||dis[i][j][3]<3))
++cnt[x0][y0];
}

int main(){
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);

scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
scanf("%d",&gph[i][j]);

for(int i=1;i<=n;++i)
for(register int j=1;j<=m;++j)
bfs(i,j);

for(int i=1;i<=n;++i)
for(register int j=1;j<=m;++j)
printf("%d%c",cnt[i][j],j==m?'\n':' ');
return 0;
}
T2:

题面:遍历树上的所有节点,求最短路径

思路:显然可以有一条路径只走一遍,其他的都要走两遍,只走一遍的选直径肯定最优,注意1e6可能卡栈空间,bfs就好了

代码:

#include<bits/stdc++.h>
#define MAXN 1000005
using namespace std; int n;

int root;

struct t1{
int to,nxt,lth;
}edge[MAXN<<1]; int cnt_edge;
int fst[MAXN];
void addedge(int x,int y,int lth){
edge[++cnt_edge].to=y;
edge[cnt_edge].nxt=fst[x];
edge[cnt_edge].lth=lth;
fst[x]=cnt_edge;

edge[++cnt_edge].to=x;
edge[cnt_edge].nxt=fst[y];
edge[cnt_edge].lth=lth;
fst[y]=cnt_edge;
}

long long dis[MAXN];
int fth[MAXN];

int que[MAXN<<1],head,tail;
int bfs(int now){
int rtn = now;

head=tail=0;
memset(fth,0,sizeof fth);

dis[now]=0;

que[tail++]=now;
while(head^tail){
now=que[head++];
for(int tmp=fst[now];tmp;tmp=edge[tmp].nxt){
int aim=edge[tmp].to;
if(aim==fth[now]) continue;
fth[aim] = now;
dis[aim] = dis[now] + edge[tmp].lth;
if(dis[aim] > dis[rtn]) rtn = aim;
que[tail++]=aim;
}
}
return rtn;
}

long long ans=0;

int read_x,read_y,read_lth;
int main(){
freopen("journey.in","r",stdin);
freopen("journey.out","w",stdout);

srand(20000218);

scanf("%d",&n);
root=rand()%n+1;

for(int i=1;i<n;++i)
scanf("%d%d%d",&read_x,&read_y,&read_lth),
ans += read_lth,
addedge(read_x,read_y,read_lth);

ans<<=1ll;
root=bfs(root);
int r2=bfs(root);
printf("%lld",ans - dis[r2]);

return 0;
}


T3:
题面:

一条路长度为D,从起点走到终点,每秒会减少A的血量(0.1秒减少0.1A的那种方式),在每一整秒的末尾可以增加一定血量,如果在任一瞬间血量小于0就失败。每获得1的初始血量需要G1的代价,每获得1的速度需要G2的代价(速度必须小于等于D),每获得1的回复量需要G3的代价,求最小花费。D和A都是1e6的,G1 G2 G3都是200的。

思路:

显然推公式,枚举速度v的取值,如果选初始血量比回复更优,肯定就全部氪在G1上,初始血量氪(ceil(A*D/v)),如果回复更优,肯定初始血量就是A,之后每秒回复也是A,对于每个速度直接把上面那两个值取min就好了,根本不需要什么分类讨论【果然还是我菜了233333】

注意因为血是每秒递减的,所以上取整操作要对(A*(D/v))整个进行

代码:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std; long long A,D,G1,G2,G3;

int main(){
freopen("run.in","r",stdin);
freopen("run.out","w",stdout);

scanf("%lld%lld%lld%lld%lld",&D,&A,&G1,&G2,&G3);

long long ans=INF;

long long tt=A*G1+A*G3;
for(int b=1;b<=D;++b)
ans=min(ans,b*G2+min(tt,(long long)(ceil((double)A*D/b)*G1)));

printf("%lld",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: