这题的和上一份报告那题有点像,不过是确定了起点和终点,而且分别有两对,按照小hh的说法就是确定了起点和终点就相当于回路问题,另一边相当于虫洞连接起来,不过他说起点为左括号,终点为右括号,这还是有点问题的,昨晚思考了一下,如果,起点和终点的位置在其他位置,而不是边界,想想楼教男人8题的那题,如果位置在中间该怎么处理,左括号和右括号的设置方法肯定不可行,而是应该像上篇报告那题要独立插头,但是这个独立插头是确定的直接确定为3状态即可。好了,思绪回到这题,这题有两条路径,如果直接用路径表示,0表示空,1表示左,2表示右,3表示其中一对的独立插头,4表示另一对独立插头,就是5进制了,还没有写这种写法,今晚写写,这题的特殊性在于求最小,按照小hh的思路,直接构造两条种轮廓线,0表示没有插头,1表示第一种插头,2表示第二种插头,求多回路最小即可,不过要处理好在起始点的位置,这题sample好多,基本上过sample就过了吧,反正我是这样,这题如果是求最大呢?应该就像那5进制了。
Run ID | User | Problem | Result | Memory | Time | Language | Code Length | Submit Time |
10896723 | 201030720425 | 3133 | Accepted | 736K | 297MS | C++ | 3095B | 2012-10-08 17:30:53 |
#include<cstdio> #include<cstring> #include<string> #include<cmath> #include<iostream> #include<algorithm> using namespace std; const int maxn=30001,INF=1<<30; int mov[15]={0,2,4,6,8,10,12,14,16,18,20}; struct node { int size,head[maxn],next[maxn]; int sta[maxn],sum[maxn]; void clear() { memset(head,-1,sizeof(head)); size=0; } void push(int st,const int v) { int hash=st%maxn; for(int i=head[hash];i>=0;i=next[i]) { if(sta[i]==st) { sum[i]=min(sum[i], v); return ; } } sta[size]=st,sum[size]=v; next[size]=head[hash],head[hash]=size++; } }dp[2]; inline int getbit(int st,int k) { return 3&(st>>mov[k]); } inline int pybit(int st,int k) { return st<<mov[k]; } inline int clrbit(int st,int a,int b) { return st&(~(3<<mov[a]))&(~(3<<mov[b])); } int n,m,gp[20][20]; int DP() { int ans=INF; dp[0].clear(); dp[0].push(0,0); int now=0,pre=1; int cnt1=0,cnt2=0; for(int i=1;i<=n;i++) { pre=now,now^=1,dp[now].clear(); for(int k=0;k<dp[pre].size;k++) dp[now].push(dp[pre].sta[k]<<2,dp[pre].sum[k]); for(int j=1;j<=m;j++) { pre=now,now^=1,dp[now].clear(); for(int k=0;k<dp[pre].size;k++) { int l=getbit(dp[pre].sta[k],j-1); int up=getbit(dp[pre].sta[k],j); int st=clrbit(dp[pre].sta[k],j,j-1); int v=dp[pre].sum[k]; // printf("%d %d %d %d %d %d %d\n",i,j,l,up,st,dp[pre].sta[k],v); if(!l&&!up) { if(gp[i][j]==0||gp[i][j]==1) dp[now].push(st,v); if(gp[i][j]==0&&i<n&&gp[i+1][j]!=1&&j<m&&gp[i][j+1]!=1) { dp[now].push(st|pybit(1,j-1)|pybit(1,j),v+1); dp[now].push(st|pybit(2,j-1)|pybit(2,j),v+1); } if(i<n&&gp[i+1][j]!=1&&gp[i][j]>=2) dp[now].push(st|pybit(gp[i][j]-1,j-1),v+1); if(j<m&&gp[i][j+1]!=1&&gp[i][j]>=2) dp[now].push(st|pybit(gp[i][j]-1,j),v+1); } else if(!l||!up) { int e=l+up; if(gp[i][j]==0) { if(i<n&&gp[i+1][j]!=1) dp[now].push(st|pybit(e,j-1),v+1); if(j<m&&gp[i][j+1]!=1) dp[now].push(st|pybit(e,j),v+1); } if(gp[i][j]==2&&e==1) { if(st==0&&cnt1>=1&&cnt2>=2) { ans=min(ans,v+1); } dp[now].push(st,v+1); } if(gp[i][j]==3&&e==2) { if(st==0&&cnt2>=1&&cnt1>=2) ans=min(ans,v+1); dp[now].push(st,v+1); } } else if(l==1&&up==1) { if(gp[i][j]>=2)continue; if(cnt1>=2) { if(cnt2>=2&&st==0) ans=min(ans,v+1); } dp[now].push(st,v+1); } else if(l==2&&up==2) { if(gp[i][j]>=2)continue; if(cnt2>=2) { if(cnt1>=2&&st==0) ans=min(ans,v+1); } dp[now].push(st,v+1); } } if(gp[i][j]==2) cnt1++; else if(gp[i][j]==3) cnt2++; } } if(ans==INF) ans=2; return ans; } int main() { while(~scanf("%d%d",&n,&m)) { if(n==m&&m==0)break; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&gp[i][j]); cout<<DP()-2<<endl; } return 0; }