小白书之最优程序

这题是一个隐式树的bfs,注意输入n对数,n对数公用同一个程序去计算结果,相当于一个程序同时去计算几对数,

然后用一个二维数组存下每次计算的值,bfs的时候注意判断下一步需要所有对数都满足可以计算的条件才能加入队列,

不过感觉他写的代码比较繁琐,而且bfs写的有些奇怪,自己不怎么想写,看了好久才看懂这个代码,主要理清俩点:

1:同一个程序去计算所有的点对数,同时计算。

2:每步计算要满足条件。

#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
char s[][4]={"ADD", "DIV", "DUP", "MUL", "SUB"};
#define INF 30000
#define maxnode 2000
int n, a[15], b[15], found, head, tail;
struct node{
  int s[15][100];
  int t[15];
  int c[15], cn;
  node() {
    memset(s, 0, sizeof(s));
    memset(t, 0, sizeof(t));
    memset(c, 0, sizeof(c));
    cn = 0;
  }
  void clear(){
    memset(s, 0, sizeof(s));
    memset(t, 0, sizeof(t));
    memset(c, 0, sizeof(c));
    cn = 0;
  }    
  void check(){
    found = 1;
    for(int i=1; i<=n; i++) if(s[i][t[i]]!=b[i]) {found=0; break;}
  }
  bool notzero(){
    for(int i=1; i<=n; i++){
        if(t[i]<=1) return true;
        else if(s[i][t[i]]==0 && s[i][t[i]-1]==0) return false;
        }
    return true;
  }
  bool onlyone(){
    for(int i=1; i<=n; i++) if(t[i]==1) return true;
    return false;
  }
  bool add(){
    if(onlyone()) return false;
    for(int i=1; i<=n; i++) if(abs(s[i][t[i]] + s[i][t[i]-1]) > INF)return false;
    for(int i=1; i<=n; i++) {s[i][t[i]-1] = s[i][t[i]] + s[i][t[i]-1]; t[i]--;}
    return true;
  }
  bool sub(){
    if(onlyone()) return false;
    for(int i=1; i<=n; i++) if(abs(s[i][t[i]-1] - s[i][t[i]]) > INF) return false;
    for(int i=1; i<=n; i++) {s[i][t[i]-1] = s[i][t[i]-1] - s[i][t[i]]; t[i]--;}
    return true;
  }
  bool mul(){
    if(onlyone()) return false;
    for(int i=1; i<=n; i++) if(abs(s[i][t[i]-1] * s[i][t[i]]) > INF) {
      return false;
    }
    for(int i=1; i<=n; i++) {s[i][t[i]-1] = s[i][t[i]-1] * s[i][t[i]]; t[i]--;}
    return true;
  }
  bool div(){
    if(onlyone()) return false;
    int fh;
    for(int i=1; i<=n; i++) {
      if(s[i][t[i]]==0) {
        return false;
      }
      if(abs(s[i][t[i]-1]) / abs(s[i][t[i]]) > INF){
        return false;
      }
    }
    for(int i=1; i<=n; i++) {
      if(s[i][t[i]-1]/s[i][t[i]]>=0) fh=1;
      else fh=-1;
      s[i][t[i]-1] = abs(s[i][t[i]-1]) / abs(s[i][t[i]]);
      s[i][t[i]-1]*=fh;
      t[i]--;
      }
    return true;
  }
  bool dup(){
    for(int i=1; i<=n; i++) {
      s[i][t[i]+1]=s[i][t[i]];
      t[i]++;
      }
    return true;
  }
  bool doit(int c){
    switch(c){
      case 0: return add(); break;
      case 4: return sub(); break;
      case 3: return mul(); break;
      case 1: return div(); break;
      case 2: return dup(); break;
    }
  }
} q[maxnode];
int main(){
    //freopen("uva.in", "r", stdin); 
        //freopen("uva.txt", "w", stdout);
    int cases = 0;
    while(scanf("%d", &n) == 1 && n){
      printf("Program %d\n", ++cases);
      memset(a, 0, sizeof(a));
      memset(b, 0, sizeof(b));
      head=0; tail=1;
      q[head].clear(); q[tail].clear();
      for(int i=1; i<=n; i++) {scanf("%d", &a[i]); q[0].s[i][q[0].t[i]=1] = a[i];}
      for(int i=1; i<=n; i++) scanf("%d", &b[i]);
      found = 0;
      node t;
      while(!found && head!=tail){
        t = q[head];
        int flag = 0;
        for(int i=0; i<5; i++){
          t.cn++;
          if(t.cn > 10)  break;
          t.c[t.cn] = i;
          if(t.doit(i)) {
            t.check();
            if(t.notzero()) {q[tail] = t; tail = (tail+1)%maxnode;} //q[tail++] = t;
            if(found) break;
          }
          t=q[head];
        }
        //head++;
        head = (head+1) % maxnode;
        //if(!found && ) break;
      }
      tail--;
      
      if(found) {
          if(q[tail].cn<1 || (q[tail].cn == 1 && !strcmp(s[q[tail].c[1]], "DUP"))) printf("Empty sequence\n");
          else {
              for(int i=1; i<=q[tail].cn; i++) printf("%s ", s[q[tail].c[i]]);
              putchar('\n');
          }    
      }    
      else printf("Impossible\n");
      putchar('\n');  
  }   
  return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值