fxtoi 开关灯
题面传送门
其实这道题是贪心+模拟。 如果这道题连搜索都没过的,看看江风扬的题解吧。
好!开始进入正题。 先给你们一段代码:
#include<cstdio>
#define maxn 30
using namespace std;
int n, a[maxn], ans = 2147483647, f[maxn];
int check(int b[]){
for(int i = 1; i < n+1; i++)
if(!b[i])return 0;
return 1;
}
int min(int a, int b){
return a<b?a:b;
}
void dfs(int c, int b[], int cnt){
if(c>n){
if(check(b)){
ans = min(ans, cnt);
}
return;
}
//取
b[c-1] = 1-b[c-1];
b[c+1] = 1-b[c+1];
b[c] = 1-b[c];
dfs(c+1, b, cnt+1);
b[c-1] = 1-b[c-1];
b[c+1] = 1-b[c+1];
b[c] = 1-b[c];
//不取
dfs(c+1, b, cnt);
return;
}
int main(){
//freopen("1.in", "r", stdin);
scanf("%d", &n);
for(int i = 1; i < n+1; i++)
scanf("%d", &a[i]);
dfs(1, a, 0);
printf("%d", ans);
return 0;
}
然后用样例进行调试。
我们发现一个很有趣的现象:
\(dfs\)没有进行到底,但是\(a_1\)已经是零了。此时运行下去已经没有意义了,于是可以\(return\)了。
这样会快一大截,但是还不够。
如果这样,会变成\(n\)方,但是还可以优化到\(n\)。
因为检查太慢!\(void\)太慢!
观察一下,可以用递推解决。
如果\(a_{n-1}\)是0,那么\(a_n\),\(a_{n-1}\),\(a_{n+1}\)一起变。
如果不是,那怎么办呢?
废话,那就不变呀!
那\(a_{1}\)呢?
那就开两个数组吧!
我就得到了这样的代码:
#include<bits/stdc++.h>
using namespace std;
int a[10000001],b[10000001],n,ans1,ans2;
int main(){
//freopen("a10.in","r",stdin);
//freopen("a10.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
b[i]=a[i];
}
if(n==1){
cout<<1-a[1]<<endl;
return 0;
}
b[1]=1-b[1];
b[2]=1-b[2];
ans2++;
for(int i=2;i<=n;i++){
if(a[i-1]==0){
a[i-1]=1-a[i-1];
a[i]=1-a[i];
a[i+1]=1-a[i+1];
ans1++;
}
if(b[i-1]==0){
b[i-1]=1-b[i-1];
b[i]=1-b[i];
b[i+1]=1-b[i+1];
ans2++;
}
}
if(a[n]==0) ans1=2147483647;
if(b[n]==0) ans2=2147483647;
if(ans1==2147483647&&ans2==2147483647) cout<<"0"<<endl;
else cout<<min(ans1,ans2)<<endl;
return 0;
}
用这样的方法可以过\(10000000\)的数据。