poj 1950 Dessert(dfs枚举,模拟运算过程)

简介:

/*
     这个代码运行的时间长主要是因为每次枚举之后都要重新计算一下和的值!
    如果要快的话,应该在dfs,也就是枚举的过程中计算出前边的数值(这种方法见第二个代码),直到最后,这样不必每一次枚举都要从头再算一遍值!
 */
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;

char ch[20];
char sign[3]={'+', '-', '.'}; 
int n, cnt;
int num[20];
int signNum[200];

void dfs(int u){
    if(u==n){
       if(signNum['+']==n-1 || signNum['+']+signNum['.']==n-1 || signNum['.']==n-1 || signNum['-']==n-1) return;
       for(int i=1; i<n; ++i){           
               num[i]=i;
               if(ch[i]=='.'){
                 int s=i, v=i;
                 while(i<n && ch[i]=='.'){
                     if(i+1>9)
                      s=s*100+(++i);
                    else s=s*10+(++i);
                 }
                 if(s>10000) return ;//非得加上这句话....然后就幸运的过了!
                 num[v]=s;
                 --i;
            }
       }
       num[n]=n;
       int s=num[1];
       for(int i=1; i<n; ++i)
             if(ch[i]!='.'){
               if(ch[i]=='+') s+=num[i+1];
               else s-=num[i+1];
          }
       if(s==0){
               ++cnt;
               if(cnt<=20){
                   for(int i=1; i<n; ++i)
                      printf("%d %c ", i, ch[i]);
                   printf("%d\n", n);
               }
       }
       return;
     }
    for(int i=0; i<3; ++i){
        ch[u]=sign[i];
        ++signNum[sign[i]];
        dfs(u+1);
        --signNum[sign[i]];
    }
}

int main(){
    while(scanf("%d", &n)!=EOF){
        cnt=0;
        dfs(1);
        printf("%d\n", cnt);
    }
    return 0;
}


/*
    清晰的思路,清晰的代码.....T^T!
 */
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
char sign[3]={'+', '-', '.'};
int n, cnt;
char ch[20];
int dir[2]={10, 100};


//pre记录的是'+' 或者是 '-'的左边的运算值, nowI记录的是其右边的值 
void dfs(char chPre, int pre, int nowI, int cur){
    if(cur==n){
        int s=-1;
        if(chPre=='+')
            s=pre+(nowI*dir[cur/10]+cur);
        else if(chPre=='-')
              s=pre-(nowI*dir[cur/10]+cur);
        //如果chPre=='.' 说明整个式子中不存在运算符号+或者-, 那最终的结果一定不是0 
        if(s==0){
            ++cnt;
            if(cnt<=20){
                for(int i=1; i<n; ++i)
                    printf("%d %c ", i, ch[i]);
                printf("%d\n", n);
            }
        }
        return ;
    }
    for(int i=0; i<3; ++i){
        ch[cur]=sign[i];
        if(ch[cur]!='.'){
            if(chPre=='+')
                dfs(ch[cur], pre+(nowI*dir[cur/10]+cur), 0, cur+1);
            else if(chPre=='-')
                dfs(ch[cur], pre-(nowI*dir[cur/10]+cur), 0, cur+1);
            else dfs(ch[cur], pre*dir[cur/10]+cur, 0, cur+1);
        }
        else{
            //之前出现了运算符,当前不是运算符 
            if(chPre=='+' || chPre=='-')//一直累计nowI的值 
                dfs(chPre, pre, nowI*dir[cur/10]+cur, cur+1);
            else //如果之前没有出现过运算符+或者-,一直累计pre的值 
                dfs(chPre, pre*dir[cur/10]+cur, 0, cur+1);
        }
    }
}

int main(){
    while(scanf("%d", &n)!=EOF){    
        cnt=0;
        dfs(' ', 0, 0, 1);
        printf("%d\n", cnt);
    } 
    return 0;
}

目录
相关文章
|
7月前
|
存储 算法 容器
精选算法题(1)——枚举符合要求的算术表达式(DFS、回溯法)
精选算法题(1)——枚举符合要求的算术表达式(DFS、回溯法)
|
7月前
|
算法 测试技术 C++
剑指offer(C++)-JZ20:表示数值的字符串(算法-模拟)
剑指offer(C++)-JZ20:表示数值的字符串(算法-模拟)
|
9月前
|
数据采集 算法 C++
DFS(深度优先搜索)详解(概念讲解,图片辅助,例题解释,剪枝技巧)
DFS(深度优先搜索)详解(概念讲解,图片辅助,例题解释,剪枝技巧)
113 0
(枚举)(模拟)(前缀和)(数组模拟哈希)(可二分)1236. 递增三元组
(枚举)(模拟)(前缀和)(数组模拟哈希)(可二分)1236. 递增三元组
47 0
(开关问题)(枚举)(模拟)(位运算)116. 飞行员兄弟
(开关问题)(枚举)(模拟)(位运算)116. 飞行员兄弟
40 0
算法学习--递归打印*到*的数
算法学习--递归打印*到*的数
(模拟)(枚举)acwing蓝桥杯1245. 特别数的和
(模拟)(枚举)acwing蓝桥杯1245. 特别数的和
45 0
L3-010 是否完全二叉搜索树 (30 分)(数组模拟)
L3-010 是否完全二叉搜索树 (30 分)(数组模拟)
78 0