http://codeforces.com/contest/812/problem/B
题意:
有n层楼,每层楼有m个房间,1表示灯开着,0表示灯关了。最两侧的是楼梯。
现在每从一个房间移动到另一个房间需要1时间,走楼梯也需要1时间,求关完所有灯所需的最少时间。
思路:
d【i】【0】表示第i层楼关完灯后从左边楼梯上楼的最少时间,d【i】【1】代表右楼梯。
预处理一下,开两个数组保存每层楼开灯房间的最左边的值和最右边的值,这样也就确定了要走的范围。
对于上面灯全部关了的楼层,可以不用去考虑它。
有个错误让我wro了好久!!
就是在dp的时候,如果这是中间的一个全部关了灯的楼层,需要特殊计算,不然计算d【i】【1】是计算错误的。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 using namespace std; 12 typedef long long ll; 13 typedef pair<int,long long> pll; 14 const int INF = 0x3f3f3f3f; 15 const int maxn=200+5; 16 17 int n,m; 18 19 int l[maxn],r[maxn]; 20 int d[maxn][2]; 21 char g[maxn][maxn]; 22 23 int main() 24 { 25 while(~scanf("%d%d",&n,&m)) 26 { 27 memset(l,0,sizeof(l)); 28 memset(r,0,sizeof(r)); 29 30 for(int i=n;i>=1;i--) 31 { 32 scanf("%s",g[i]); 33 { 34 for(int j=0;j<m+2;j++) 35 { 36 if(g[i][j]=='1') 37 { 38 r[i]=j; 39 if(l[i]==0) l[i]=j; 40 } 41 } 42 } 43 } 44 45 for(int i=n;i>=1;i--) 46 { 47 if(l[i]==0 && r[i]==0) n--; 48 else break; 49 } 50 51 if(n==0) 52 { 53 puts("0"); 54 continue; 55 } 56 57 if(n==1) 58 { 59 printf("%d\n",r[1]); 60 continue; 61 } 62 63 memset(d,INF,sizeof(d)); 64 65 d[1][0]=2*r[1]+1; 66 d[1][1]=m+1+1; 67 68 for(int i=2;i<n;i++) 69 { 70 if(l[i]==0 && r[i]==0) 71 { 72 d[i][0]=d[i-1][0]+1; 73 d[i][1]=d[i-1][1]+1; 74 } 75 else 76 { 77 d[i][0]=min(d[i-1][0]+2*r[i],d[i-1][1]+m+1)+1; 78 d[i][1]=min(d[i-1][0]+m+1,d[i-1][1]+2*(m+1-l[i]))+1; 79 } 80 } 81 82 int ans=min(d[n-1][0]+r[n],d[n-1][1]+m+1-l[n]); 83 84 printf("%d\n",ans); 85 } 86 return 0; 87 }