24点游戏(vijos1134)

本文介绍了一种解决24点游戏问题的枚举算法。通过记录两数、三数间的运算结果,尝试所有可能组合来寻找达到24点的方法。算法分为两步:先计算两数、三数的所有可能结果;再验证这些结果是否能通过加减乘除得到24。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法:枚举
 
这道题调了半天的说,RP不佳啊,错在两个地方了,一个是不等于写成了大于,一个是数组开小了……
其实这道题还是挺好做的,只要分析到位就行了。
1.先存上四个数。
2.开数组记录两个数之间的加减乘除。
3.开数组记录三个数之间的加减乘除。
4.最后的结果有两种可能:
    两个数与两个数之间构成24点。
    三个数与一个数构成24点。

  分别枚举一下即可。

program vijos1134;

var
 tot:longint;
 f:array [0..4,0..4,0..6000] of real;
 ff:array [0..4,0..4,0..4,0..6000] of real;
 c:array [0..4,0..4] of longint;
 cc:array [0..4,0..4,0..4] of longint;
 a:array [0..4] of longint;
 s:string;

procedure init;
var
 i:longint;
begin
 readln(s);
 for i:=1 to length(s) do
  begin
   if s[i]=' ' then continue
   else if s[i]='0' then continue
   else if (s[i]='1') and (s[i+1]='0') then
    begin
     inc(tot);
     a[tot]:=10;
    end
   else
    begin
     case s[i] of
      'A':begin
           inc(tot);
           a[tot]:=1;
           continue;
          end;
      'J':begin
           inc(tot);
           a[tot]:=11;
           continue;
          end;
      'Q':begin
           inc(tot);
           a[tot]:=12;
           continue;
          end;
      'K':begin
           inc(tot);
           a[tot]:=13;
           continue;
          end;
     end;{case}
     inc(tot);
     a[tot]:=ord(s[i])-48;
    end;
  end;
end;

procedure main1;
var
 i,j,k:longint;
begin
 fillchar(f,sizeof(f),0);
 for i:=1 to 4 do
  begin
   for j:=1 to 4 do
    begin
     if (i<>j) and (c[i,j]=0) then
      begin
       inc(c[i,j]);
       f[i,j,c[i,j]]:=a[i]+a[j];
       inc(c[i,j]);
       f[i,j,c[i,j]]:=a[i]-a[j];
       inc(c[i,j]);
       f[i,j,c[i,j]]:=a[j]-a[i];
       inc(c[i,j]);
       f[i,j,c[i,j]]:=a[i]*a[j];
       if a[j]<>0 then
        begin
         inc(c[i,j]);
         f[i,j,c[i,j]]:=a[i]/a[j];
        end;
       if a[i]<>0 then
        begin
         inc(c[i,j]);
         f[i,j,c[i,j]]:=a[j]/a[i];
        end;
       c[j,i]:=-1;
      end;
    end;
  end;
end;

procedure main2;
var
 i,j,k,t:longint;
begin
 fillchar(cc,sizeof(cc),0);
 fillchar(ff,sizeof(ff),0);
 for k:=1 to 4 do
  begin
   for i:=1 to 4 do
    begin
     for j:=1 to 4 do
      begin
       if (i<>j) and (i<>k) and (k<>j) and (c[i,j]>0) and (cc[k,i,j]=0) then
        begin
         for t:=1 to c[i,j] do
          begin
           inc(cc[k,i,j]);
           ff[k,i,j,cc[k,i,j]]:=f[i,j,t]+a[k];
           inc(cc[k,i,j]);
           ff[k,i,j,cc[k,i,j]]:=a[k]-f[i,j,t];
           inc(cc[k,i,j]);
           ff[k,i,j,cc[k,i,j]]:=f[i,j,t]-a[k];
           inc(cc[k,i,j]);
           ff[k,i,j,cc[k,i,j]]:=f[i,j,t]*a[k];
           if a[k]<>0 then
            begin
             inc(cc[k,i,j]);
             ff[k,i,j,cc[k,i,j]]:=f[i,j,t]/a[k];
            end;
           if f[i,j,t]<>0 then
            begin
             inc(cc[k,i,j]);
             ff[k,i,j,cc[k,i,j]]:=a[k]/f[i,j,t];
            end;
          end;
         cc[k,j,i]:=-1;
         cc[i,j,k]:=-1;
         cc[i,k,j]:=-1;
         cc[j,i,k]:=-1;
         cc[j,k,i]:=-1;
        end;
      end;
    end;
  end;
end;

procedure print1;
var
 i,j,k,l,t:longint;
begin
 for i:=1 to 4 do
  begin
   for j:=1 to 4 do
    begin
     for k:=1 to 4 do
      begin
       for l:=1 to 4 do
        begin
         if (j<>k) and (j<>l) and (k<>l) and (j<>i) and (k<>i) and (l<>i) and (cc[j,k,l]>0) then
          begin
           for t:=1 to cc[j,k,l] do
            begin
             if abs(a[i]+ff[j,k,l,t]-24)<0.00001 then
              begin
               writeln(1);
               close(input);
               close(output);
               halt;
              end;
             if abs(a[i]-ff[j,k,l,t]-24)<0.00001 then
              begin
               writeln(1);
               close(input);
               close(output);
               halt;
              end;
             if abs(ff[j,k,l,t]-a[i]-24)<0.00001 then
              begin
               writeln(1);
               close(input);
               close(output);
               halt;
              end;
             if abs(a[i]*ff[j,k,l,t]-24)<0.00001 then
              begin
               writeln(1);
               close(input);
               close(output);
               halt;
              end;
             if (ff[j,k,l,t]<>0) and (abs(a[i]/ff[j,k,l,t]-24)<0.00001) then
              begin
               writeln(1);
               close(input);
               close(output);
               halt;
              end;
             if (a[i]<>0) and (abs(ff[j,k,l,t]/a[i]-24)<0.00001) then
              begin
               writeln(1);
               close(input);
               close(output);
               halt;
              end;
            end;
          end;
        end;
      end;
    end;
  end;
end;

procedure print2;
var
 i,j,k,l,t1,t2:longint;
begin
 for i:=1 to 4 do
  begin
   for j:=1 to 4 do
    begin
     for k:=1 to 4 do
      begin
       for l:=1 to 4 do
        begin
         if (i<>j) and (i<>k) and (i<>l) and (j<>k) and (j<>l) and (k<>l) and (c[i,j]>0) and (c[k,l]>0) then
          begin
           for t1:=1 to c[i,j] do
            begin
             for t2:=1 to c[k,l] do
              begin
               if abs(f[i,j,t1]+f[k,l,t2]-24)<0.00001 then
                begin
                 writeln(1);
                 close(input);
                 close(output);
                 halt;
                end;
               if abs(f[i,j,t1]-f[k,l,t2]-24)<0.00001 then
                begin
                 writeln(1);
                 close(input);
                 close(output);
                 halt;
                end;
               if abs(f[k,l,t2]-f[i,j,t1]-24)<0.00001 then
                begin
                 writeln(1);
                 close(input);
                 close(output);
                 halt;
                end;
               if abs(f[i,j,t1]*f[k,l,t2]-24)<0.00001 then
                begin
                 writeln(1);
                 close(input);
                 close(output);
                 halt;
                end;
               if (f[k,l,t2]<>0) and (abs(f[i,j,t1]/f[k,l,t2]-24)<0.00001) then
                begin
                 writeln(1);
                 close(input);
                 close(output);
                 halt;
                end;
               if (f[i,j,t1]<>0) and (abs(f[k,l,t2]/f[i,j,t1]-24)<0.00001) then
                begin
                 writeln(1);
                 close(input);
                 close(output);
                 halt;
                end;
              end;
            end;
          end;
        end;
      end;
    end;
  end;
end;

begin
 assign(input,'VJ1134.in'); reset(input);
 assign(output,'VJ1134.out'); rewrite(output);

 init;
 main1;
 main2;
 print1;
 print2;
 writeln(0);

 close(input); close(output);
end.



问题一 字串变换 描述: 已知有两个字串 A, B 及一组字串变换的规则: A1 -> B1 A2 -> B2 规则的含义为:在 A中的子串 A1 可以变换为 B1、A2 可以变换为 B2 … 例如:A='abcd' B='xyz' 变换规则为: ‘abc’ -> ‘xu’ ‘ud’ -> ‘y’ ‘y’ -> ‘yz’ 则此时,A 可以经过一系列的变换变为 B,其变换的过程为: ‘abcd’ -> ‘xud’ -> ‘xy’ -> ‘xyz’ 共进行了三次变换,使得 A 变换为B。 现在的问题是:对于给定的A,B 及一组字串变换的规则,若A能在10步内(包含10步)变换成B,则输出所需的最短变换步数,否则输出NO ANSWER。 数据范围: 字串A,B长度小于等于20 规则总数小于等于6 输入格式: 从文件convert.in读入 第一行为两个字符串,第二行至文件尾为变换规则 变换规则一行为两个字符串A1 B1用空格分隔,表示 A1 -> B1 A B A1 B1 A2 B2 ... ... 输出格式: 输出到convert.out中 当变换步数在10步(包含10步)内,那么输出这个数字 否则,输出”NO ANSWER" 特别提醒: 这道题目很像WordLadder,用BFS也更为方便。但是,Lab2的主题是递归,所以大家这道题目不允许用BFS,必须是递归形式的。 对于每个测试用例,时间限制为1秒,实在不行,2秒也能接受。 规则没有优先级,所有的规则都是平等的,没有优先顺序。 可能会同时出现 a -> b a -> c这样的规则,就是说a可以转换成b,也可以转换成c。 问题二 24 描述: 几十年前全世界流行一种叫作“24”数字扑克游戏。作为游戏者将得到4个1-13(在扑克牌里用A代替1,J代替11,Q代替12,K代替13)之间的自然数作为操作数,并对这四个数进行适当的术运(加,减,乘,除)使得最后结果为24。 例如: 4个数字为3 8 10 Q 那么一个方案可以是Q * ( 10 / ( 8-3 ) ) = 24 现在你的任务是实现一个自动24器,对于任意的4个1-13的自然数,如果可以24则输出一个合理方案,若无解则输出“NO ANSWER”。 数据范围: 4个数字属于S={1,2,3,4,5,6,7,8,9,10,J,Q,K} J,Q,K为字符 输入格式: 从文件calculator.in读入 一行4个数字,以空格分隔 输出格式: 输出到文件calculator.out中 一个字符串,表示最后的运方案,符号与数字之间、符号与符号之间用空格分隔 如Q * ( 10 / ( 8 - 3 ) ) = 24 (Q与*之间有空格,(与10之间有空格) 或者当没有可行方案时输出“NO ANSWER"。 特别提醒: 这道题目还是用递归。 表达式中的每个子表达式的结果可以是小数,即例如 (3+3/7)*7=24 是合法的。 去除多余的括号。例如,对于2 2 3 8 这四个数字,一个解可以是3 * ( ( 8 + 2 ) - 2 ),但是要求是去除多余的括号,即最后的结果应该是3 * ( 8 + 2 - 2)。就是说,可以不用的括号都要去掉。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值