【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题不久就会成为黑题

后排鸣谢@找寻 大佬

posted @ 2018-10-03 18:41  vercont  阅读(130)  评论(0编辑  收藏  举报