Time Limit: 5000MS | Memory Limit: 65536K | |
Description
There is a rectangular area containing n × m cells. Two cells are marked with “2”, and another two with “3”. Some cells are occupied by obstacles. You should connect the two “2”s and also the two “3”s with non-intersecting lines. Lines can run only vertically or horizontally connecting centers of cells without obstacles.
Lines cannot run on a cell with an obstacle. Only one line can run on a cell at most once. Hence, a line cannot intersect with the other line, nor with itself. Under these constraints, the total length of the two lines should be minimized. The length of a line is defined as the number of cell borders it passes. In particular, a line connecting cells sharing their border has length 1.
Fig. 1(a) shows an example setting. Fig. 1(b) shows two lines satisfying the constraints above with minimum total length 18.
Figure 1: An example of setting and its solution
Input
The input consists of multiple datasets, each in the following format.
n m row1 … rown
n is the number of rows which satisfies 2 ≤ n ≤ 9. m is the number of columns which satisfies 2 ≤ m ≤ 9. Each rowi is a sequence of m digits separated by a space. The digits mean the following.
0:
Empty
1:
Occupied by an obstacle
2:
Marked with “2”
3:
Marked with “3”
The end of the input is indicated with a line containing two zeros separated by a space.
Output
For each dataset, one line containing the minimum total length of the two lines should be output. If there is no pair of lines satisfying the requirement, answer “0
” instead. No other characters should be contained in the output.
Sample Input
5 50 0 0 0 00 0 0 3 02 0 2 0 01 0 1 1 10 0 0 0 32 32 2 00 3 36 52 0 0 0 00 3 0 0 00 0 0 0 01 1 1 0 00 0 0 0 00 0 2 3 05 90 0 0 0 0 0 0 0 00 0 0 0 3 0 0 0 00 2 0 0 0 0 0 2 00 0 0 0 3 0 0 0 00 0 0 0 0 0 0 0 09 93 0 0 0 0 0 0 0 20 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 02 0 0 0 0 0 0 0 39 90 0 0 1 0 0 0 0 00 2 0 1 0 0 0 0 30 0 0 1 0 0 0 0 20 0 0 1 0 0 0 0 30 0 0 1 1 1 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 09 90 0 0 0 0 0 0 0 00 3 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 2 3 20 0
Sample Output
182171205243
Source
#include#include #include #include #include #include #include using namespace std;const int STATE = 59049+1000; const int Mod = 10007;#define For(i,n) for(int i=1;i<=n;i++)#define Rep(i,l,r) for(int i=l;i<=r;i++)#define Down(i,r,l) for(int i=r;i>=l;i--)struct statedp{ int head[Mod],next[STATE],f[STATE],state[STATE]; int size; void clear(){memset(head,-1,sizeof(head));size = 0;} void push(int st,int ans){ int Key = st % Mod; for(int p = head[Key];p!=-1;p=next[p]) if(st==state[p]){ f[p] = min(f[p],ans); return; } state[size] = st;f[size] = ans;next[size] = head[Key]; head[Key] = size++; }}dp[2];int n,m,maze[12][12],code[12];void init(){ For(i,n) For(j,m) scanf("%d",&maze[i][j]);}void dpblock(int i,int j,int cur){ int Lim = (j==m) ? (2) : (0); Rep(i,0,dp[cur].size-1) dp[cur^1].push(dp[cur].state[i] >> Lim , dp[cur].f[i]);}void shift(){ Down(i,m,1) code[i] = code[i-1];code[0] = 0;}int encode(){ int ret = 0; Rep(i,0,m) ret = ret << 2 | code[i]; return ret;}void decode(int st){ Down(i,m,0) code[i] = st & 3 , st >>= 2;}void dpblank(int i,int j,int cur){ Rep(k,0,dp[cur].size-1){ decode(dp[cur].state[k]); int Left = code[j-1] , Up = code[j]; if(maze[i][j]>=2){ if(Left&&Up) continue; int CODE = (maze[i][j]==2)?(1):2; if(Left||Up){ if(Left+Up!=CODE) continue; code[j-1] = code[j] = 0; if(j==m) shift(); dp[cur^1].push(encode(),dp[cur].f[k]); }else{ if(i