码迷,mamicode.com
首页 > 其他好文 > 详细

ZOJ 3213

时间:2014-05-30 00:11:41      阅读:258      评论:0      收藏:0      [点我收藏+]

标签:c   style   class   blog   code   tar   

bubuko.com,布布扣
  1 /*
  2 ZOJ 3213
  3 
  4 好吧,看过那种括号表示法后,就崩溃了,实在受不了。情况复杂,写了两天,人也有点傻X了,只能放弃,转而用最小表示法。
  5 最小表示法不难写:
  6 
  7  1)首先,要承认路径上有格子不选的情况,于是,在00的情况下,可扩展,也可不选。
  8  2)不能出现环,因而不能有L=U的情况出现。
  9  3)以下是模版代码,类同是必然。但转而求路径数的时候,应当去掉不扩展的情况,同时,在IF(L|U)的情况下,亦不必考虑当前是否为最后一个格子,
 10     只需按写的转移即可。
 11  4)增加独立插头时,必须在总的独立插头数小于2的情况下进行。
 12 
 13   注意:之所以不能出现两个插头,是因为,独立插头是单向的路径,不能进了又出。限制这个条件是非常有必要的。而在此处我本以为若限制了条件就得不出
 14   最优解,而其实,因为存在不选的状态,限制了这个条件依然是可以有最优解的。
 15 */
 16 #include<stdio.h>
 17 #include<string.h>
 18 #include<algorithm>
 19 #include<iostream>
 20 using namespace std;
 21 
 22 const int MAXD=15;
 23 const int HASH=10007;
 24 const int STATE=1000010;
 25 
 26 int N,M;
 27 int maze[MAXD][MAXD];
 28 int code[MAXD];
 29 int ch[MAXD];
 30 int num;
 31 int ans;
 32 
 33 struct HASHMAP
 34 {
 35     int head[HASH],next[STATE],size;
 36     int state[STATE],dp[STATE];
 37     void init()
 38     {
 39         size=0;
 40         memset(head,-1,sizeof(head));
 41     }
 42     void push(int st,int ans)
 43     {
 44         int i,h=st%HASH;
 45         for(i=head[h];i!=-1;i=next[i])
 46           if(state[i]==st)
 47           {
 48               if(dp[i]<ans)dp[i]=ans;
 49               return;
 50           }
 51         state[size]=st;
 52         dp[size]=ans;
 53         next[size]=head[h];
 54         head[h]=size++;
 55     }
 56 }hm[2];
 57 void decode(int *code,int m,int st)
 58 {
 59     num=st&7;//??????
 60     st>>=3;
 61     for(int i=m;i>=0;i--)
 62     {
 63         code[i]=st&7;
 64         st>>=3;
 65     }
 66 }
 67 int encode(int *code,int m)
 68 {
 69     int cnt=1;
 70     memset(ch,-1,sizeof(ch));
 71     ch[0]=0;
 72     int st=0;
 73     for(int i=0;i<=m;i++)
 74     {
 75         if(ch[code[i]]==-1)ch[code[i]]=cnt++;
 76         code[i]=ch[code[i]];
 77         st<<=3;
 78         st|=code[i];
 79     }
 80     st<<=3;
 81     st|=num;
 82     return st;
 83 }
 84 void shift(int *code,int m)
 85 {
 86     for(int i=m;i>0;i--)code[i]=code[i-1];
 87     code[0]=0;
 88 }
 89 void dpblank(int i,int j,int cur)
 90 {
 91     int k,left,up;
 92     for(k=0;k<hm[cur].size;k++)
 93     {
 94         decode(code,M,hm[cur].state[k]);
 95         left=code[j-1];
 96         up=code[j];
 97         if(left&&up)
 98         {
 99             if(left!=up)
100             {
101                 code[j-1]=code[j]=0;
102                 for(int t=0;t<=M;t++)
103                   if(code[t]==up)
104                      code[t]=left;
105                 if(j==M)shift(code,M);
106                 hm[cur^1].push(encode(code,M),hm[cur].dp[k]+maze[i][j]);
107             }
108         }
109         else if(left||up)
110         {
111             int t;
112             if(left)t=left;
113             else t=up;
114             if(maze[i][j+1])
115             {
116                 code[j-1]=0;
117                 code[j]=t;
118                 hm[cur^1].push(encode(code,M),hm[cur].dp[k]+maze[i][j]);
119             }
120             if(maze[i+1][j])
121             {
122                 code[j-1]=t;
123                 code[j]=0;
124                hm[cur^1].push(encode(code,j==M?M-1:M),hm[cur].dp[k]+maze[i][j]);
125             }
126             if(num<2)   //封住一端,增加一个独立插头。
127             {
128                 num++;
129                 code[j-1]=code[j]=0;
130                 hm[cur^1].push(encode(code,j==M?M-1:M),hm[cur].dp[k]+maze[i][j]);
131             }
132         }
133         else
134         {
135             code[j-1]=code[j]=0;      //讨论简单路径,只需不讨论不选的情况就可以了。
136            hm[cur^1].push(encode(code,j==M?M-1:M),hm[cur].dp[k]);   
137             if(maze[i][j+1]&&maze[i+1][j])
138             {
139                 code[j-1]=code[j]=13;
140                 hm[cur^1].push(encode(code,M),hm[cur].dp[k]+maze[i][j]);
141             }
142             if(num<2)
143             {
144                 num++;
145                 if(maze[i][j+1])
146                 {
147                     code[j]=13;
148                     code[j-1]=0;
149                     hm[cur^1].push(encode(code,M),hm[cur].dp[k]+maze[i][j]);
150                 }
151                 if(maze[i+1][j])
152                 {
153                     code[j-1]=13;
154                     code[j]=0;
155                    hm[cur^1].push(encode(code,j==M?M-1:M),hm[cur].dp[k]+maze[i][j]);
156                 }
157             }
158         }
159     }
160 }
161 void dpblock(int i,int j,int cur)
162 {
163     int k;
164     for(k=0;k<hm[cur].size;k++)
165     {
166         decode(code,M,hm[cur].state[k]);//?????!!!
167         code[j-1]=code[j]=0;
168         if(j==M)shift(code,M);
169         hm[cur^1].push(encode(code,M),hm[cur].dp[k]);
170     }
171 }
172 void init()
173 {
174     scanf("%d%d",&N,&M);
175     ans=0;
176     memset(maze,0,sizeof(maze));//???????
177     for(int i=1;i<=N;i++)
178       for(int j=1;j<=M;j++)
179       {
180           scanf("%d",&maze[i][j]);
181           if(maze[i][j]>ans)ans=maze[i][j];
182       }
183 }
184 void solve()
185 {
186     int i,j,cur=0;
187     hm[cur].init();
188     hm[cur].push(0,0);
189     for(i=1;i<=N;i++)
190        for(int j=1;j<=M;j++)
191        {
192            hm[cur^1].init();
193            if(maze[i][j])dpblank(i,j,cur);
194            else dpblock(i,j,cur);
195            cur^=1;
196        }
197     for(i=0;i<hm[cur].size;i++)
198       if(hm[cur].dp[i]>ans)
199         ans=hm[cur].dp[i];
200     printf("%d\n",ans);
201 }
202 int main()
203 {
204     int T;
205     scanf("%d",&T);
206     while(T--)
207     {
208         init();
209         solve();
210     }
211     return 0;
212 }
View Code

 

ZOJ 3213,布布扣,bubuko.com

ZOJ 3213

标签:c   style   class   blog   code   tar   

原文地址:http://www.cnblogs.com/jie-dcai/p/3758040.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!