About Search & DP

About Search & DP

sanpin

03/24/08


DP与其它算法有关系,当然包括了搜索。

DPDFS

记忆化递归的实现大家都用过,如果是递归实现的是DFS,就是这里说的了,不再举例。

DpBFS

记忆化搜索,怎么不包括BFS呢。这种题大家也做过,只是没意识到。

一个最朴素的BFS效率并不是很高,大家都很自觉地为它加了剪枝之类。有一类重要的剪枝就是记忆,如使用Hash等。经典BFS实现中的“color”,是一体现。再举一例。

例:

Johnny Hates Mathhttp://acm.pku.edu.cn/JudgeOnline/problem?id=3516

description

Johnny is on probation! He has failed so many math courses and the Department has forced him to register in a remedial math course. He must pass the course or he’d be expelled from the University. In an attempt to impress his professor, Johnny is typing all his assignments on the computer. The latest assignment is rather simple, Johnny was given a set of problems to solve. Each problem had a list of one or more numbers that Johnny was supposed to add. Johnny has worked all night on the assignment, neatly typing his solution to each problem using a word processor as seen here:

4+12+3=19

As usual, Johnny woke up late, he hardly had the time to print the assignment and rush to class. Only in the classroom did he discover that, due to a printer driver problem, non of the plus signs were printed. The above line was printed as:

4123=19

Write a program to figure out where the pluses are supposed to be. All what Johnny remembers is that all the numbers were positive; None of the numbers, other than possibly the sum, had more than 5 digits; And none of the numbers had a zero as the left-most digit.

Input

Your program will be tested on one or more expressions. Each expression is specified on a single line. No line will be longer than 256 characters. The last line, which is not part of the test cases, will be 0=0.

Output

For each expression in the input, your program must print a line of the form:

k. result

Where k is the expression number (starting at 1), and result is the expression with the necessary plus signs in place. There are no spaces in result. If there are more than one possible solution, print a solution that requires the least number of plus signs. Knowing how bad Johnny is in arithmetic, it is possible that there is no solution, in which case your program should print "IMPOSSIBLE" as the result.

Sample Input

4123=19 15442147612367219875=472 111=8 0=0

Sample Output

1. 4+12+3=19 2. 15+44+21+47+61+23+67+21+98+75=472 3. IMPOSSIBLE 明显可以DP.A[i]表到第i个可以生成的值的集合,易有转移方程。但问题是这集合如何表示?可以像邻接表一样的形式,应该是可以的。A[i]中会不会有大量重复元素呢?这是可能的,如(111111111……)在后面就有大量重复了,怎么办?去重吧。可以寻找一个Hash函数,开一张大大的表来实现。 上述步骤实际上是实现了一BFS。可以用明显的BFS的形式来实现,更清晰。  这题的无聊之处在数据暴大,私以为没必要这样。	

Source Code

Problem: 3516


User: sanpin

Memory: 151592K


Time: 7985MS

Language: G++


Result: Accepted

  •  

    #include <set> #include <iostream> #define M 300 #define MAX_LEN 10000000 #define HASH_SIZE 500000 #include <algorithm> using namespace std;  int num[M],len; int res;  set<pair<int,int> > rec;  bool hash[HASH_SIZE][257];  struct Node{     int prev;     int currValue;     int endPosInNum; };  Node que[MAX_LEN]; int rear,front;  // sum[i]  is sum till i-1 + int sum[M]; void preproc(){     sum[len] =0 ;     for (int i=len-1; i>=0; --i)         sum[i] = sum[i+1] + num[i]; }  bool expand(int s){     int i;     int st=que[s].endPosInNum+1;     int en = min(st+4,len-1);                  if (num[st] ==0) return true;     int tmp = 0;     int tt;     for (i=st; i<=en; ++i){         tmp = (tmp<<3) + (tmp<<1) + num[i];         tt = que[s].currValue + tmp;         if ((tt + sum[i+1])>res)break;         if (hash[tt%HASH_SIZE][i] == true) continue;         hash[tt%HASH_SIZE][i] = true;                  que[rear].prev = s;         que[rear].currValue = tt;         que[rear].endPosInNum = i;                  if (i==len-1 && que[rear].currValue == res)return false;         ++rear;              if (rear >=MAX_LEN)            while(1);     }         return true; }  void print(int s){     int p=que[s].prev;     if (p ==0){         for (int i=0; i<=que[s].endPosInNum; ++i)             printf("%d",num[i]);         return;     }          print(p);     printf("+");     for (int i=que[p].endPosInNum+1; i<=que[s].endPosInNum;++i)         printf("%d",num[i]); }   void bfs(){     memset(hash,false,sizeof(hash));     front = rear = 0;     que[0].prev = -1;     que[0].currValue = 0;     que[0].endPosInNum = -1;     ++rear;          while (front !=rear){         if (!expand(front)) break;         ++front;     }     if (front == rear){         printf("IMPOSSIBLE/n");             }else{         print(rear);         printf("=%d/n",res);     } }  int main(){     int i,iCase=0;     char in[M];     while (1){         scanf("%s",in);         if (in[0]=='0')break;         ++iCase;         printf("%d. ",iCase);         for (i=0; in[i]!='=';++i){             num[i] = in[i] - '0';         }         len = i;         ++i;               res = atoi(in+i);         preproc();         bfs();     } }

其它的Search

也有吧,一时没想起对应题目来。

 




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值