http://codeforces.com/contest/812/problem/B
【题意】
有一个n*m的棋盘,每个小格子有0或1两种状态,现在要把所有的1都变成0,问最少的步数是多少?初始位置在左下角,只有把下面一层的1都变成0后才可以到上一层,只有在每层的最右边和最左边可以向上走(up),否则只能左右移动(left or right)。只要经过1,就可以把1变成0,只要把最后一个1,就可以立即停止操作。
【Accepted】
1 #include <iostream> 2 #include <stdio.h> 3 #include <cmath> 4 #include <vector> 5 #include <algorithm> 6 #include <set> 7 #include <map> 8 #include <queue> 9 #include <deque> 10 #include <stack> 11 #include <string> 12 #include <bitset> 13 #include <ctime> 14 #include<algorithm> 15 #include<cstring> 16 using namespace std; 17 int n,m; 18 const int maxn=1e2+5; 19 char s[maxn]; 20 int a[16][maxn]; 21 int sum[16]; 22 int ans; 23 int fir[16]; 24 int sec[16]; 25 const int inf=0x3f3f3f3f; 26 int index; 27 void dfs(int cur,int flag,int cnt) 28 { 29 if(cur==index) 30 { 31 if(flag) 32 { 33 int t=cnt+sec[index]-1; 34 ans=min(ans,t); 35 return; 36 } 37 else 38 { 39 int t=cnt+m+2-fir[index]; 40 ans=min(ans,t); 41 return; 42 } 43 } 44 if(flag) 45 { 46 if(sum[cur]) 47 { 48 dfs(cur-1,0,cnt+m+2); 49 dfs(cur-1,1,cnt+2*(sec[cur]-1)+1); 50 } 51 else 52 { 53 dfs(cur-1,1,cnt+1); 54 } 55 } 56 else 57 { 58 if(sum[cur]) 59 { 60 dfs(cur-1,1,cnt+m+2); 61 dfs(cur-1,0,cnt+2*(m+2-fir[cur])+1); 62 } 63 else 64 { 65 dfs(cur-1,0,cnt+1); 66 } 67 } 68 69 } 70 int main() 71 { 72 while(~scanf("%d%d",&n,&m)) 73 { 74 memset(sum,0,sizeof(sum)); 75 memset(fir,-1,sizeof(fir)); 76 memset(sec,0,sizeof(sec)); 77 ans=inf; 78 for(int i=1;i<=n;i++) 79 { 80 scanf("%s",s+1); 81 for(int k=1;k<=m+2;k++) 82 { 83 a[i][k]=s[k]-'0'; 84 sum[i]+=a[i][k]; 85 //每层最右的1的位置 86 if(a[i][k]) 87 { 88 sec[i]=k; 89 } 90 //每层最左的1的位置 91 if(a[i][k]&&fir[i]==-1) 92 { 93 fir[i]=k; 94 } 95 } 96 } 97 int cou=0; 98 //index表示走到第几层为止,因为上面的都是0 99 index=0; 100 for(int i=1;i<=n;i++) 101 { 102 cou+=sum[i]; 103 if(cou!=0) 104 { 105 index=i; 106 break; 107 } 108 } 109 //特判,如果数据都是0 110 if(index==0) 111 { 112 printf("0 "); 113 continue; 114 } 115 //分别表示第几层,当前层的初始位置在最左边还是最右边,步数 116 dfs(n,1,0); 117 cout<<ans<<endl; 118 } 119 return 0; 120 }
时间复杂度是2^15
没有考虑的都是0的corner case,疯狂wa