1. 程式人生 > >poj---3276Face The Right Way

poj---3276Face The Right Way

\n pro turn 開始 次數 mes scanf 翻轉 tail

題意:

  給一個01串,一次操作可以翻轉連續的K的值,求最小的操作次數m及其對應的k值

  題目鏈接

tips:

  1.考慮第i頭牛來分析,它的狀態跟誰和什麽操作有關。

  2.分析題目性質,找到問題求解的步驟,在求解中減小問題的規模。----題目問題肯定有解決流程。

  3.遞推的思想

  4.看網上的題解還是鞥啟發思路的,書和blog各有其好,結合食用效果最佳。

  5.白書上的遞推公式有點坑啊。。

  6.代碼中sum保存當前位置的前k-1格的操作數

技術分享圖片
//先要對問題進行分析,找出求解問題的思路
//將問題的規模逐漸縮小,橫推過去
//區間的影響範圍和 遞推公式的理解
//只記錄操作的次數,跟線段樹的懶標記有點像
//卡在輸入了..然而並不是,是中間有個循環i的賦值錯了 //網上的題解對輸入的處理是定義了一個字符數組,%s輸入,最後只用判斷第一位 //用getchar(),把回車字符過濾了也可以 //sum的解釋https://blog.csdn.net/thudaliangrx/article/details/50444975 #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int MAXN=5001; int dir[MAXN]; int f[MAXN]; int n; int clc(int
K){ memset(f,0,sizeof(f)); int res=0; int sum=0; for(int i=0;i+K<=n;i++){ if(( dir[i]+ sum ) %2 != 0){ res++; f[i]=1; } sum+=f[i]; if(i-K+1 >= 0) { sum-=f[i-K+1]; } } //數組下標是從0開始的,所以第n個元素對應的下標是n-1 for
(int i=n-K+1;i<n;i++){//(N-1)-0...(N-1)-(K-1)...(N-1)-K if( (dir[i]+sum)%2 != 0){ return -1; } if(i-K+1 >= 0){ sum-=f[i-K+1]; } } return res; } int main(){ while(scanf("%d",&n)!=EOF){ getchar(); for(int i=0;i<n;i++){ /*char x[5]; scanf("%s",&x); if(x[0] == ‘B‘){ dir[i]=1; } else{ dir[i]=0; } //getchar(); */ char x; scanf("%c",&x); if(x == B){ dir[i]=1; } else{ dir[i]=0; } getchar(); } int K=1,M=n; for(int k=1;k<= n;k++){ int m=clc(k); if(m >= 0 && M>m){ M=m; K=k; } } printf("%d %d\n",K,M); } return 0; }
View Code

poj---3276Face The Right Way