【题目】http://poj.org/problem?id=1700
【题意】求开锁最少步骤
【算法】递归
【题解】首先按照题意写了一个递归程序,是超时的。但发现了一个规律,就是若修改第N个节点值时,从0到N-1都为0时要花费2个N次方-1次操作。于是从尾到首少秒一次数据串,第几数次遇到的1对应要花费的步骤,第偶数次遇见的1对应节约的步骤。还有N为1000,最大结果(2的1000次方-1)为大数,所以用java大数完成。
【注意】普通递归会超时,但是有助于我们发现规律。
超时代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[1000];
int ans;
void dg(int i,int x){
if(i<0||a[i]==x) return;
ans++;
a[i]=x;
dg(--i,1);
for(i--;i>=0;i--)dg(i,0);
}
int main(){
int n,i;
while(scanf("%d",&n)!=EOF){
for(i=0;i<n;i++)scanf("%d",&a[i]);
ans=0;
for(i=n-1;i>=0;i--)dg(i,0);
printf("%d\n",ans);
}
return 0;
}
【测试数据】
4
1 0 1 0
10
1 0 0 0 0 0 0 0 0 1
10
0 0 0 0 0 0 0 0 1 1
10
0 0 0 0 0 0 0 1 1 1
10
0 0 0 0 0 0 1 1 1 1
10
0 1 0 0 0 0 0 0 0 1
ans:
6
1022
512
767
640
1020
【AC代码】
import java.io.*;
import java.util.*;
import java.math.*;
public class Main{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
BigInteger a;
int[] s = new int[1000];
int n,i,f;
while(in.hasNext()){
n = in.nextInt();
for(i=0;i<n;i++)s[i]=in.nextInt();
a=BigInteger.ZERO;
f=1;
for(n--;n>=0;n--)
if(s[n]==1){
if(f==1){
a=a.add(new BigInteger("2").pow(n+1).subtract(BigInteger.ONE));
f=0;
}
else{
a=a.subtract(new BigInteger("2").pow(n+1).subtract(BigInteger.ONE));
f=1;
}
}
System.out.println(a);
}
}
}
【心得】我要不断提高效率!