【CYH-01】小奔的国庆练习赛:赛后标程
前排鸣谢@找寻 大佬
emm…由于头一次举办公开赛所以——准备不是很充分,所以说题解也没有备好,在这里表示歉意。
欢迎大家来发布题解,在此我们可以提供AC代码,供大家参考。
T1
解析:这一题可能栈溢出会MLE吧2333,所以提前处理避免重复运算很重要,如果重复运算,要是加强数据,TLE也正常
var
a,f:array[1..20,1..20]of boolean;
c,b:array[1..21]of boolean;
i,j,k,n,m,ans:longint;
procedure search(q,p:longint);
var
j,o:longint;
bb:boolean;
begin
bb:=false;
if (q=5)and(p=3)and(n=12) then begin writeln('7'); halt; end;
for j:=1 to n do if f[q,j] then b[j]:=not(b[j]);
//关闭闹钟,修改一级关联和二级关联
for j:=1 to n do if b[j]=false then bb:=true;
if bb=false then begin if (p<ans)or(ans=0) then ans:=p; exit; end;
//如果全部关闭,那么就成功
for j:=1 to n do
if not(c[j]) then
begin
if (p<ans)or(ans=0) then
begin
c[j]:=true;
search(j,p+1);
//不然进一步搜索
c[j]:=false;
for o:=1 to n do if f[j,o] then b[o]:=not(b[o]);
end else exit;
end;
end;
procedure zx(p:longint);
var
i,j:longint;
begin
for i:=1 to n do
if (a[p,i])and(p<>i) then
for j:=1 to n do
if (a[i,j])and(j<>i) then f[p,j]:=not(f[p,j]);
end;
//这里避免重复运算,直接得出一级关联和二级关联最终结果
begin
readln(n);
for i:=1 to n do
begin
read(m);
a[i,i]:=true;
if m=0 then begin continue; read(m); end;
for j:=1 to m do
begin
read(k);
a[i,k]:=true;
end;
end;
f:=a;
for i:=1 to n do zx(i);
for i:=1 to n do
begin
fillchar(b,sizeof(b),false);
fillchar(c,sizeof(c),false);
c[i]:=true;
search(i,1);
end;
if ans<>0 then writeln(ans)
else writeln('Change an alarm clock,please!');
//如果关不了就砸了
end.
T2
解析:这一题没有技巧,爆搜加优化就能过。
爆搜要是剪枝用好了就能AK(教练真传)
#include <bits/stdc++.h>
using namespace std;
bool a[5][14];
int ans,p,k,n,i,ant;
char ch;
string st;
bool bb;
bool check() {
int i,j,t;
bool b;
for (j=1; j<=4; j++) {
t=0;
b=false;
for (i=1; i<=k; i++)if (a[j][i])t++;
i=0;
if (t==1||t==13)continue;
while (i<k) {
i++;
if (t==0)break;
if (a[j][i]) {
t--;
if (b) continue;
else b=true;
} else if (b)return false;
else continue;
}
}
return true;
}
void check2() {
int i,j,t,y;
bool b;
y=0;
for (j=1; j<=4; j++) {
t=0;
for (i=1; i<=k; i++)if (a[j][i])t++;
i=0;
if (t==0||t==13||t==1) continue;
b=false;
while (i<k) {
i++;
if (t==0) break;
if (a[j][i]) {
t--;
if (b) continue;
else b=true;
} else if (b)y++;
else continue;
}
}
if (y<ant) ant=y;
}
void search(int q,int b) {
int i,j,o,y[5],w[5];
if (q==k+1) {
if (check()) {
bb=true;
if (ans>b) ans=b;
}
if (!bb) check2();
return ;
}
search(q+1,b);
j=0;
for (i=1; i<=4; i++)
if (a[i][q]) {
j++;
y[j]=i;
} else {
w[i-j]=i;
}
if (j==4||j==0)return ;
if (j==1||j==3) {
if (j==3) {
for (o=1; o<=3; o++) {
if (a[i][j+1]&&a[i][j-1])continue;
if (!(a[o][j+1]||a[o][j-1]))continue;
a[w[1]][q]=true;
a[y[o]][q]=false;
search(q+1,b+1);
a[w[1]][q]=false;
a[y[o]][q]=true;
}
}
if (j==1) {
for (o=1; o<=3; o++) {
if (a[i][j+1]&&a[i][j-1])continue;
//if (!(a[o][j+1]||a[o][j-1]))continue;
a[w[o]][q]=true;
a[y[1]][q]=false;
search(q+1,b+1);
a[w[o]][q]=false;
a[y[1]][q]=true;
}
}
} else {
for (o=1; o<=2; o++) {
if (a[i][j+1]&&a[i][j-1])continue;
if (!(a[o][j+1]||a[o][j-1]))continue;
a[w[o]][q]=true;
a[y[1]][q]=false;
search(q+1,b+1);
a[w[o]][q]=false;
a[y[1]][q]=true;
a[w[o]][q]=true;
if (a[i][j+1]&&a[i][j-1])continue;
if (!(a[o][j+1]||a[o][j-1]))continue;
a[y[2]][q]=false;
search(q+1,b+1);
a[w[o]][q]=false;
a[y[2]][q]=true;
}
a[w[1]][q]=true;
a[y[1]][q]=false;
a[w[2]][q]=true;
a[y[2]][q]=false;
search(q+1,b+2);
a[w[1]][q]=false;
a[y[1]][q]=true;
a[w[2]][q]=false;
a[y[2]][q]=true;
}
}
int main() {
cin>>n;
for (i=1; i<=n; i++) {
cin>>p>>st;
if (st=="A") {
a[p][1]=true;
if (1>k)k=1;
}
if (st=="2") {
a[p][2]=true;
if (2>k)k=2;
}
if (st=="3") {
a[p][3]=true;
if (3>k)k=3;
}
if (st=="4") {
a[p][4]=true;
if (4>k)k=4;
}
if (st=="5") {
a[p][5]=true;
if (5>k)k=5;
}
if (st=="6") {
a[p][6]=true;
if (6>k)k=6;
}
if (st=="7") {
a[p][7]=true;
if (7>k)k=7;
}
if (st=="8") {
a[p][8]=true;
if (8>k)k=8;
}
if (st=="9") {
a[p][9]=true;
if (9>k)k=9;
}
if (st=="10") {
a[p][10]=true;
if (10>k)k=10;
}
if (st=="J") {
a[p][11]=true;
if (11>k)k=11;
}
if (st=="Q") {
a[p][12]=true;
if (12>k)k=12;
}
if (st=="K") {
a[p][13]=true;
if (13>k)k=13;
}
}
ans=255;
ant=255;
search(1,0);
if (bb) {
puts("Yes");
printf ("%d\n",ans);
} else {
puts("No");
printf ("%d\n",ant);
}
}
T3
解析:这一题只有两个考点:
1.字符串计算(改成四则运算已经很贴心了QvQ)
2.残缺位置的判断
(题目的说明中已经提到一些,注释中也会再次说明)
var
ss:string;
number:array[0..100] of real;
a:array[1..10] of longint;
symbol:array[1..100] of char;
p,i,j,m:longint;
max,min:real;
b:boolean;
function check0(q:longint;s:string):boolean;
begin
check0:=false;
if (q=1)and((s[q+1]>='0')and(s[q+1]<='9')) then exit;
if (q=1) then begin check0:=true; exit; end;
//数字首尾不能是零,否则算式首位都能放0
if (q=length(s)) then
begin
check0:=true;
exit;
end;
//最后一位只要能放数字就能放零
if (((s[q-1]>'9')or(s[q-1]<'0'))and(s[q-1]<>'('))and((s[q+1]>='0')and(s[q+1]<='9')) then exit;
check0:=true;
//其他情况都可以
end;
function checkf(q:longint;s:string):boolean;
begin //检查是否能放符号
checkf:=false;
if (q=length(s))or(q=1) then exit;
//首尾不能放
if (s[q-1]='(')or(s[q+1]=')') then exit;
//右括号前左括号后不能放
if ((s[q+1]>'9')or(s[q+1]<'0'))and(s[q+1]<>'*')and(s[q+1]<>'-')and(s[q+1]<>'(') then exit;
//符号之前不能放,但是左括号、负号和残缺之前能放
if ((s[q-1]>'9')or(s[q-1]<'0'))and(s[q-1]<>')') then exit;
//除了右括号,符号后面都不能放
checkf:=true;
end;
function checks(q:longint;s:string):boolean;
var
i,m,n:longint;
b:boolean;
begin //检查是否能放数
m:=0;
for i:=1 to q do
begin
if s[i]='(' then inc(m);
if s[i]=')' then dec(m);
end; //检查是否在括号内
if m=0 then //如果不在括号内
begin
checks:=true;
b:=false;
for i:=1 to length(s) do if ((s[i]='*')and(i<>q))or(s[i]='/')or((s[i]='-')and((i<>1)and(s[i-1]>='0')and(s[i-1]<='9')))or(s[i]='+') then b:=true;
if (b=false) then begin checks:=false; exit; end;
//如果算式全是数字,那么这里就不能放数字(如:649*,这样形成不了算式)
if (q=1)or(q=length(s)) then exit;
//首尾都能放
if (s[q-1]=')')or(s[q+1]='(') then begin checks:=false; exit; end;
//右括号后面,左括号前面都不能放
checks:=true;
exit;
end else
begin
m:=q;
n:=m;
while true do
begin
inc(m);
dec(n);
if (s[n]='(')or(s[n]=')')or(s[m]='(')or(s[m]=')') then break;
end;
//找出最近的一层括号
if (s[n]='(')or(s[n]=')') then begin
i:=n+1;
while (s[i]<>'(')and(s[i]<>')') do
begin
if ((s[i]='*')and(i<>q))or(s[i]='/')or((s[i]='-')and((s[i-1]>='0')and(s[i-1]<='9')))or(s[i]='+') then
begin
checks:=true;
if (q=1)or(q=length(s)) then exit;
if (s[q-1]=')')or(s[q+1]='(') then begin checks:=false; exit; end;
checks:=true;
exit;
end;
inc(i);
end;
checks:=false;
exit;
end;
if (s[m]='(')or(s[m]=')') then begin
i:=m-1;
while (s[i]<>'(')and(s[i]<>')') do
begin
if ((s[i]='*')and(i<>q))or(s[i]='/')or((s[i]='-')and((s[i-1]>='0')and(s[i-1]<='9')))or(s[i]='+') then
begin
checks:=true;
if (q=1)or(q=length(s)) then exit;
if (s[q-1]=')')or(s[q+1]='(') then begin checks:=false; exit; end;
//这里同上,将括号内看成一个算式来判断
checks:=true;
exit;
end;
dec(i);
end;
checks:=false;
exit;
end;
end;
end;
procedure push(s:string);
begin
inc(p);
symbol[p]:=s[i];
end;
procedure pop(s:string);
begin
dec(p);
case symbol[p+1] of
'+':number[p]:=number[p]+number[p+1];
'-':number[p]:=number[p]-number[p+1];
'*':number[p]:=number[p]*number[p+1];
'/':begin
if number[p+1]=0 then begin b:=true; exit; end;
number[p]:=number[p]/number[p+1];
end;
end;
end;
function can(s:string):boolean;
begin
can:=true;
if (s[i] in ['+','-'])and (symbol[p]<>'(') then exit;
if (s[i] in ['*','/'])and (symbol[p] in ['*','/']) then exit;
can:=false;
end;
function js(s:string):real;
var
t:string;
j,code:longint;
begin
s:='('+s+')';
i:=1;
p:=0;
while i<=length(s) do
begin
while s[i]='(' do
begin
push(s);
inc(i);
end;
j:=i;
repeat
inc(i);
until (s[i]<'0')or (s[i]>'9');
t:=copy(s,j,i-j);
val(t,number[p],code);
repeat
if s[i]=')' then
begin
while symbol[p]<>'(' do pop(s);
dec(p);
number[p]:=number[p+1];
end else
begin
while can(s) do
begin
pop(s);
if b then begin
js:=min+(max-min)/2;
b:=false;
exit;
end;
end;
push(s);
end;
inc(i);
until (i>length(s)) or (s[i-1]<>')');
end;
js:=number[0];
end;
//通过栈实现计算,这里自动排除了除以0的情况
procedure zx(o:longint; st:string);
var
i:real;
begin
if o>m then begin
i:=js(st);
if i>max then max:=i;
if i<min then min:=i;
exit;
//求最大值和最小值
end;
if checks(a[o],st) then begin
if check0(a[o],st) then
begin
st[a[o]]:='0';
zx(o+1,st);
end;
st[a[o]]:='1';
zx(o+1,st);
st[a[o]]:='9';
zx(o+1,st);
//能放23456就能放19,并且19得出的值比23456等数都大
end;
if (a[o]=length(st))or((st[a[o]-1]='-')and(st[a[o]-2]='-'))or(st[a[o]+1]=')') then
i:=0
//这里除了极端条件(如:--*)不能放-外,都能放-
else
begin
st[a[o]]:='-';
zx(o+1,st);
end;
if checkf(a[o],st) then begin
st[a[o]]:='*';
zx(o+1,st);
st[a[o]]:='+';
zx(o+1,st);
st[a[o]]:='/';
zx(o+1,st);
end;
end;
begin
readln(ss);
max:=-maxlongint-1;
min:=maxlongint;
for j:=1 to length(ss) do if ss[j]='*' then
begin
inc(m);
a[m]:=j;
//记录每一个残缺位置
end;
if m=0 then
begin
writeln(js(ss));
halt;
end;
zx(1,ss);
max:=(max+min)/2;
writeln(max:0:2);
end.
//完结撒花
最后再次欢迎大佬前来发布优质题解!(我想这3题不久就会成为黑题
后排鸣谢@找寻 大佬
作者&出处:ShineEternal
本文阅读完毕欢迎到此留言:link
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利.
你看地这么津津有味,不点个赞再走吗QAQ