POJ3276 Face The Right Way 开关问题

①每个K从最左边进行考虑

②f[i]=[i,i+k-1]是否进行反转:1代表是,0代表否

∑ (i)(i=i+1-K+1) f[j]=∑ (i-1)(i=i-K+1) f[j]+f[i]-f[i-K+1]

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<queue>
 5 #include<map>
 6 #include<vector>
 7 #include<set>
 8 #include<string>
 9 #include<cmath>
10 #include<cstring>
11 using namespace std;
12 int n;
13 int dir[5005],f[5005];//dir牛的方向0F1B,f是[i,i-k+1]是否反转 
14 int cal(int k)//k求最小操作数 
15 {
16     memset(f,0,sizeof(f));
17     int res=0;
18     int sum=0;//f的和
19     for(int i=0;i+k<=n;i++)
20     {
21         if((dir[i]+sum)%2!=0)
22         {
23             res++;
24             f[i]=1;    
25         }    
26         sum+=f[i];
27         if(i-k+1>=0)
28         {
29             sum-=f[i-k+1];
30         }
31     }
32     //检查后面的牛有没有朝后 
33     for(int i=n-k+1;i<n;i++)
34     {
35         if((dir[i]+sum)%2!=0)
36         {
37             return -1;//无解 
38         }
39         if(i-k+1>=0)
40         {
41             sum-=f[i-k+1];
42         }
43     }
44     return res;
45 }
46 void solve()
47 {
48     int resK=1,resM=n;
49     for(int k=1;k<=n;k++)
50     {
51         int m=cal(k);
52         if(m>=0&&resM>m)
53         {
54             resM=m;
55             resK=k;
56         }
57     }
58     printf("%d %d\n",resK,resM);
59 }
60 int main()
61 {
62     scanf("%d",&n);
63     for(int i=0;i<n;i++)
64     {
65         getchar();
66         char c=getchar();
67         if(c=='B')
68             dir[i]=1;
69         else
70             dir[i]=0;
71     }
72     solve();
73     return 0;
74 }
posted @ 2020-01-23 18:16  付玬熙  阅读(122)  评论(0编辑  收藏  举报