大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

时间:2021-10-04 10:47:36

数据

http://files.cnblogs.com/htfy/data.zip

简要题解

桌球碰撞

纯模拟,注意一开始就在袋口和v=0的情况。v和坐标可以是小数。为保险起见最好用extended/double类型。

program prob1;

var
ans:array[0..6,0..600] of longint;
n,i,j:longint;
a0,r0,px,py,vx,vy,left,t,newp:extended;
flag:boolean; function dist(x1,y1,x2,y2:extended):extended;inline;begin exit( sqrt(sqr(x1-x2)+sqr(y1-y2))); end;
function store(num:longint;x,y:extended):boolean;inline;
begin
//writeln('x=',x,' y=',y);
//readln;
if x=0 then
if (y>=0) and (y<=r0) then
begin
inc(ans[1,0]);
ans[1,ans[1,0]]:=num;
exit(true);
end else
if (y>=5-r0) and (y<=5) then
begin
inc(ans[4,0]);
ans[4,ans[4,0]]:=num;
exit(true);
end; if x=10 then
if (y>=0) and (y<=r0) then
begin
inc(ans[3,0]);
ans[3,ans[3,0]]:=num;
exit(true);
end else
if (y>=5-r0) and (y<=5) then
begin
inc(ans[6,0]);
ans[6,ans[6,0]]:=num;
exit(true);
end; if y=0 then
if (x>=0) and (x<=r0) then
begin
inc(ans[1,0]);
ans[1,ans[1,0]]:=num;
exit(true);
end else
if (x>=5-r0) and (x<=5+r0) then
begin
inc(ans[2,0]);
ans[2,ans[2,0]]:=num;
exit(true);
end else
if (x>=10-r0) and (x<=10) then
begin
inc(ans[3,0]);
ans[3,ans[3,0]]:=num;
exit(true);
end; if y=5 then
if (x>=0) and (x<=r0) then
begin
inc(ans[4,0]);
ans[4,ans[4,0]]:=num;
exit(true);
end else
if (x>=5-r0) and (x<=5+r0) then
begin
inc(ans[5,0]);
ans[5,ans[5,0]]:=num;
exit(true);
end else
if (x>=10-r0) and (x<=10) then
begin
inc(ans[6,0]);
ans[6,ans[6,0]]:=num;
exit(true);
end;
exit(false);
end; begin readln(n,r0,a0);
fillchar(ans,sizeof(ans),0);
for i:=1 to n do
begin
//writeln('i=',i, ' ');
readln(px,py,vx,vy); left:=(vx*vx+vy*vy)/(2*a0);
if (vx=vy) and (vx=0) then begin {writeln('inti');}store(i,px,py); continue; end;
//process
while left>=0 do
begin
if store(i,px,py) then break;
flag:=false; if vx<0 then
begin
t:=px/(-vx);
newp:=t*vy+py;
if (newp>=0) and (newp<=5) then
begin
flag:=true;
left:=left-dist(px,py,0,newp);
px:=0;
py:=newp;
vx:=-vx;
end;
end else
if vx>0 then
begin
t:=(10-px)/(vx);
newp:=t*vy+py;
if (newp>=0) and (newp<=5) then
begin
flag:=true;
left:=left-dist(px,py,10,newp);
px:=10;
py:=newp;
vx:=-vx;
end;
end; if (vy>0) and not flag then
begin
t:=(5-py)/vy;
newp:=t*vx+px;
if (newp>=0) and (newp<=10) then
begin
flag:=true;
left:=left-dist(px,py,newp,5);
px:=newp;
py:=5;
vy:=-vy;
end;
end else
if vy<0 then
begin
t:=py/(-vy);
newp:=t*vx+px;
if (newp>=0) and (newp<=10) then
begin
flag:=true;
left:=left-dist(px,py,newp,0);
px:=newp;
py:=0;
vy:=-vy;
end;
end; end;
end;
for i:=1 to 6 do
begin
write(ans[i,0]);
if ans[i,0]<>0 then write(' ');
for j:=1 to ans[i,0] do
if j<ans[i,0] then write(ans[i,j],' ') else write(ans[i,j]);
writeln;
end; end.

旋转圆盘

DP,设F[t,i,j]为第t时刻到达第i层第j块的最大得分和。

则F[t,i,j]=w[i,j]+Max{

F[t-1,i,j]//不动

,F[t-1,i,prev(j)]//从前面走过来

,F[t-1,i,next(j)]//从后面走过来

,F[t-1,i-1,j]//从上面跳下来

,F[t-2,i-1,k]+w[i-1,k] (k<>j) //从上面转后跳下来

}

注意到最后一种情况若朴素查找Max{f[t-2,i-1,k] k<>j}则会使转移代价成为O(m),从而整个程序的复杂度会达到O(tn m^2)从而TLE

我们可以记录每一个t,i下F[t,i,k]的最大值、最大值时的maxk 和 除最大值以外的F[t,i,k]max(k<>maxk)

这样我们就可以在O(1)时间内得到Max{f[t-2,i-1,k] k<>j}了

注意到W较大,用int64存储

用滚动数组压缩空间,滚动数组mod 3较慢,不如直接mod 4=and 3快

program prob2;

var
t0,n,m,i,j,t:longint;
ans:int64;
a:array[0..300,0..300] of int64;
f:array[-2..3,-2..300,-2..300] of int64;
max1,max2,pos1,pos2:array[-2..3,-2..300] of int64; function prev(P:int64):int64;inline; begin if p=m then exit(1) else exit(p+1); end;
function next(P:int64):int64;inline; begin if p=1 then exit(m) else exit(p-1); end;
function max(a,b:int64):int64;inline; begin if a>b then exit(a);exit(b); end; begin readln(n,m,t0);
for i:=1 to n do
begin
for j:=1 to m do
read(a[i,j]);
readln;
end; fillchar(f,sizeof(f),$81);
//max1[t0,i] max2 pos1 pos2
fillchar(max1,sizeof(max1),$81);
fillchar(max2,sizeof(max2),$81); f[0,1,1]:=0;
for t:=1 to t0 do
for i:=1 to n do
begin
max1[t and 3,i]:=-maxlongint;max2[t and 3,i]:=-maxlongint;
for j:=1 to m do
begin
f[t and 3,i,j]:=f[(t-1) and 3,i,j];
f[t and 3,i,j]:=max(f[(t-1) and 3,i,j],f[(t-1) and 3,i,prev(j)]);
f[t and 3,i,j]:=max(f[t and 3,i,j],f[(t-1) and 3,i,next(j)]);
f[t and 3,i,j]:=max(f[t and 3,i,j],f[(t-1) and 3,i-1,j]);
if j<>pos1[(t-2) and 3,i-1] then f[t and 3,i,j]:=max(f[t and 3,i,j],max1[(t-2) and 3,i-1]+a[i-1,pos1[(t-2) and 3,i-1]]) else
f[t and 3,i,j]:=max(f[t and 3,i,j],max2[(t-2) and 3,i-1]+a[i-1,pos2[(t-2) and 3,i-1]]); f[t and 3,i,j]:=f[t and 3,i,j]+a[i,j]; if f[t and 3,i,j]>max1[t and 3,i] then begin max1[t and 3,i]:=f[t and 3,i,j];pos1[t and 3,i]:=j; end
else
if f[t and 3,i,j]>max2[t and 3,i] then begin max2[t and 3,i]:=f[t and 3,i,j];pos2[t and 3,i]:=j; end; end;
end; ans:=-maxlongint;
for i:=1 to n do
for j:=1 to m do
ans:=max(ans,f[t0 and 3,i,j]);
writeln(ans); end.

弹幕游戏

直接输出0或1什么的都有30分入账(HT:所以说这是水题模拟赛)

正解是对抗搜索。甲是Max游戏者 乙是Min游戏者

alpha-beta减枝考虑到这是noip模拟赛就没加(其实是因为出不出来卡朴素的数据)(跑了一个上午的对拍器没找到合理的数据)

细节很多,自己看代码吧

program prob3;

Const
TLEFT=1;
TRIGHT=2;
TUP=3;
TDOWN=4;
PLAYERA=false;
PLAYERB=true;
dx:array[1..5] of longint=(-1,1,0,0,0);
dy:array[1..5] of longint=(0,0,1,-1,0);
illegal=$1235;//不合法状态,用一个够大的数标记 Type TBullet=record//子弹定义
x,y,dir:integer;//x y 子弹坐标 dir运动方向,详见前
ava:boolean;//是否要继续处理子弹的运动,如果已经跑到外面了就赋ava=false
end;
TSelfState=record
top,sx,sy,ax,ay,bx,by:longint;//一个游戏者的状态 包含了小怪的位置和自机位置和子弹栈
bullet:array[0..55] of TBullet;
end;
TState=record
pa,pb:TSelfState;//状态 包含了甲乙游戏者的两个网格
score,t:integer;
end; Var
now:TState;
t0:longint;
q:array[0..20,false..true] of longint; Function max(a,b:longint):longint;inline;begin if a>b then exit(a);exit(b); end;
Function min(a,b:longint):longint;inline;begin if a<b then exit(a);exit(b); end; Function missed(var ss:TselfState):boolean;inline;//判断一个网格内是否已经中弹
var
i:longint;
begin
with ss do
begin
if (sx=ax) and (sy=ay) then exit(true);//撞到小怪了
if (sx=bx) and (sy=by) then exit(true);
for i:=1 to top do
if bullet[i].ava and (sx=bullet[i].x) and (sy=bullet[i].y) then exit(true);//撞到子弹了
exit(false);
end;
end; procedure createbullet(var ss:TselfState;px,py,pdir:longint);inline;//在一个游戏者的网格中创建子弹
begin
if not((px>=1) and (px<=5) and (py>=1) and (py<=6)) then exit;//子弹在外面不用创建了
inc(ss.top);
with ss.bullet[ss.top] do
begin
dir:=pdir;
x:=px;
y:=py;
ava:=true;
end;
end; procedure movebullet(var ss:TselfState);inline;//子弹的移动
var
i:longint;
begin
for i:=1 to ss.top do
with ss.bullet[i] do
if ava then
begin
x:=x+dx[dir];
y:=y+dy[dir];
if not((x>=1) and (x<=5) and (y>=1) and (y<=6)) then ava:=false;//子弹到外面就不用处理了
end;
end; procedure createmoz(var ss:TselfState;pt:longint);inline;//创建小怪的子弹
begin
if odd(pt) then //奇数秒 a小怪产生子弹
begin
createbullet(ss,ss.ax+1,ss.ay,TRIGHT);
createbullet(ss,ss.ax-1,ss.ay,TLEFT);
createbullet(ss,ss.ax,ss.ay-1,TDOWN);
end else
begin //偶数秒 b小怪产生子弹
createbullet(ss,ss.bx+1,ss.by,TRIGHT);
createbullet(ss,ss.bx-1,ss.by,TLEFT);
createbullet(ss,ss.bx,ss.by-1,TDOWN);
end; end; function expand(player:boolean;apro:longint):boolean;inline;//apro 操作方式 1左 2右 3上 4下 5ATK 返回表示该操作是否合法 若合法即改写状态
begin if player=PLAYERA then
with now.pa do
begin
if (sx=5) and (apro=2) then exit(false);
if (sx=1) and (apro=1) then exit(false);
if (sy=1) and (apro=4) then exit(false);
if (sy=6) and (apro=3) then exit(false); //在边界还需要向外移动肯定不合法
if missed(now.pa) then dec(now.score); //中弹判定
if apro<5 then begin sx:=sx+dx[apro];sy:=sy+dy[apro]; end else//需要移动的情况
begin //产生子弹的情况
createbullet(now.pb,sx-1,sy+2,TDOWN);
createbullet(now.pb,sx,sy+2,TDOWN);
createbullet(now.pb,sx+1,sy+2,TDOWN);
end;
movebullet(now.pa);//子弹移动
createmoz(now.pa,now.t); //产生小怪子弹
//inc(now.t); a游戏者操作后回合数不会+1~
exit(true);
end; if player=PLAYERB then
with now.pb do
begin
if (sx=5) and (apro=2) then exit(false);
if (sx=1) and (apro=1) then exit(false);
if (sy=1) and (apro=4) then exit(false);
if (sy=6) and (apro=3) then exit(false);
if missed(now.pb) then inc(now.score);
if apro<5 then begin sx:=sx+dx[apro];sy:=sy+dy[apro]; end else
begin
createbullet(now.pa,sx-1,sy+2,TDOWN);
createbullet(now.pa,sx,sy+2,TDOWN);
createbullet(now.pa,sx+1,sy+2,TDOWN);
end;
movebullet(now.pb);
createmoz(now.pb,now.t);
inc(now.t); //b操作完后回合数+1
exit(true);
end; end; function search(dpt:longint;player:boolean):longint;
var
i,o:longint;
oldnow:Tstate;
begin
q[dpt,player]:=illegal;
search:=illegal;
if dpt=t0+1 then
exit(now.score);
oldnow:=now;
for i:=1 to 5 do
begin
now:=oldnow;
if not expand(player,i) then continue;
if player=playera then o:=search(dpt,not player) else o:=search(dpt+1,not player);
if o<>illegal then
if search=illegal then
search:=o
else
if player=playera then //轮到a行动,他会找分差最大的方案
search:=max(search,o)
else
search:=min(search,o);//b行动,分差最小的方案
q[dpt,player]:=search; if player=playera then //alpha-beta剪枝
begin
if (search>q[dpt-1,not player]) and (q[dpt-1,not player]<>illegal) then exit;
end else
if (search<q[dpt,not player]) and (q[dpt,not player]<>illegal) then exit;
end;
end; begin
readln(t0);
filldword(q,sizeof(q) div 4,illegal);
with now.pa do
begin
top:=0;
readln(sx,sy,ax,ay,bx,by);
end;
with now.pb do
begin
top:=0;
readln(sx,sy,ax,ay,bx,by);
end;
now.score:=0;
now.t:=1;
writeln(search(1,playera)); end.

大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程的更多相关文章

  1. 10&period;6-10&period;7 牛客网NOIP模拟赛题解

    留个坑... upd:估计这个坑补不了了 如果还补不了就删了吧

  2. 『7&period;5 NOIP模拟赛题解』

    T1 Gift Description ​ 人生赢家老王在网上认识了一个妹纸,然后妹纸的生日到了,为了表示自己的心 意,他决定送她礼物.可是她喜爱的东西特别多,然而他的钱数有限,因此他想 知道当他花一 ...

  3. 『7&period;3 NOIP模拟赛题解』

    T1 gift Description ​ 夏川的生日就要到了.作为夏川形式上的男朋友,季堂打算给夏川买一些生日礼物. ​ 商店里一共有种礼物.夏川每得到一种礼物,就会获得相应喜悦值Wi(每种礼物的喜 ...

  4. 队爷的讲学计划 CH Round &num;59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...

  5. 队爷的Au Plan CH Round &num;59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...

  6. 队爷的新书 CH Round &num;59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...

  7. CH Round &num;58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

  8. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  9. CH Round &num;55 - Streaming &num;6 &lpar;NOIP模拟赛day2&rpar;

    A.九九归一 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2355%20-%20Streaming%20%236%20(NOIP模拟赛day2)/九九归一 题 ...

随机推荐

  1. Java命令行解析:apache commons-cli

    http://commons.apache.org/proper/commons-cli/usage.html Apache Commons CLI用于解析命令行选项,也可以输出详细的选项说明信息. ...

  2. sqlserver 用户、账号、安全等问题小汇

    一.孤立账号 SQL Server 的用户安全管理分两层,整个SQL Server 服务器一层,每个数据库一层. 在服务器层的帐号,叫登录账户(SQL Server:服务器角色),可以设置它管理整个S ...

  3. grep时排除指定的文件和目录

    参考:http://winterth.duapp.com/notes/ar03s04.htmlhttp://blog.sina.com.cn/s/blog_7169c8ce0100qkyf.html ...

  4. MFC上下浮动与渐入渐出消息提示框实现

    类似QQ与360软件,消息提示有两种.上下浮动.渐入渐出. 1.上下浮动提示框实现 机制,定时器响应上下浮动消息. 主要API:MoveWindow. 源码如下UpDownTipDlg.h.UpDow ...

  5. Linux使用快捷键,who命令,rm命令,ps命令,cd,命令kill命令,find命令,grep命令,tar命令&lpar;gz、tar、bz2&rpar;,用户管理,vim配置的一部分,相关命令

    1.进入Ubuntu开场后的终端窗口的快捷键是:           ctrl + alt+t:通过这个命令能够打开终端. ctrl + alt+t:通过这个命令能够打开终端. 再开一个tab选项卡式 ...

  6. 分布式监控系统开发【day37】&colon;需求讨论(一)

    本节内容 为什么要做监控? 常用监控系统设计讨论 监控需求讨论 如何实现监控服务器的水平扩展? 监控系统架构设计 一.为什么要做监控? 熟悉IT监控系统的设计原理 开发一个简版的类Zabbix监控系统 ...

  7. 【Atcoder yahoo-procon2019-qual D】&Tab;Ears

    Atcoder yahoo-procon2019-qual D 题意:给你\(L\)个耳朵(???),以及一条范围从\(0\)到\(L\)的数轴,你可以选择一个出发点,从该点开始随意走动,如果经过了\ ...

  8. TroubleShoot&colon; Enable Developer Mode in Windows 10 Insider Preview Build 10074

    There is a known issue in Windows 10 Insider Preview build 10074 (see here). Developers cannot enabl ...

  9. &lbrack;精&rsqb;Odoo 8&period;0深入浅出开发教程-模块开发基础

    參考资料点击这里. 构建Odoo模块 模块组成 业务对象 业务对象声明为Python类, 由Odoo自己主动加载. 数据文件 XML或CSV文件格式, 在当中声明了元数据(视图或工作流).配置数据(模 ...

  10. iptables 工具的使用

    试验建议:关闭CentOS 7 或 CentOS 6的防火墙 (systemctl stop firewalld ; systemctl disable firewalld 或 service ipt ...