题意:
给一个0,1序列,每次连续翻转k个,求翻转m次将序列全置0的最优二元组(k,m)。
分析:
题意说是要优先优化m,但不一定要优先枚举m,可以先枚举k再在内循环中处理。这题关键是把独立关系转化为依赖关系,每位与前面一样为0,不一样为1。这样翻转一位i时,只需改变i+k,不用改变i,i+1,i+2,i+k-1。
代码:
//poj 3276
//sep9
//n^2
#include <iostream>
using namespace std;
int a[5012],tmp[5012];int main()
{int n;scanf("%d",&n);char pre,ch;pre='F';for(int i=1;i<=n;++i){scanf(" %c",&ch);if(ch==pre)a[i]=0;else a[i]=1;pre=ch;}int ans_k,ans_m=INT_MAX;for(int k=1;k<=n;++k){int sum=0;memcpy(tmp,a,sizeof(a));for(int i=1;i+k-1<=n;++i)if(tmp[i])++sum,tmp[i+k]^=1;for(int i=n-k+2;i<=n;++i){if(tmp[i]){sum=INT_MAX;break;}}if(sum<ans_m)ans_k=k,ans_m=sum;}printf("%d %d",ans_k,ans_m);return 0;
}
一开始写搓了一个,思维定式先枚举首要优化变量m去了:logn*n^3...
#include <iostream>
using namespace std;
const int MAXN=5012;
int n;
int a[MAXN],tmp[MAXN];int check(int operation)
{ for(int k=1;k<=n;++k){int ok=1,cnt=0;for(int i=0;i<n;++i)tmp[i]=a[i]; for(int i=0;i<n;){if(tmp[i]==0)++i;else{if(i+k>n){ok=0;break;} ++cnt;if(cnt>operation){ok=0;break;} for(int j=i;j<i+k;++j){tmp[j]^=1;} ++i;} }if(ok==1)return k;}return 0;
}int main()
{scanf("%d",&n);char s[8];for(int i=0;i<n;++i){scanf("%s",s);if(s[0]=='B')a[i]=1;elsea[i]=0; }int K,M;int l=0,r=n+1;while(l<r){int mid=(l+r)/2;if(K=check(mid)){M=mid;r=mid;}elsel=mid+1; }printf("%d %d",K,M);return 0;
}