Dreamoon and MRT

Dreamoon and MRT

题目链接:

http://codeforces.com/group/gRkn7bDfsN/contest/212299/problem/B


只需要考虑相对位置,设a0位置为0
枚举
由于对称性,可以设第一步向右,这样总时间减少一半
递归的话省去了cnt部分,直接从O(N2^N-1)变成了O(2^N-1)
可以分析一下几个代码的优化过程

#include <bits/stdc++.h>
using namespace std;
int n, a[30], b[30], c, cnt, ans = 25;
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    for (int i = 0; i < (1 << n); i++) {
        int s = 0;
        c++;
        cnt = 1;
        b[0] = s;
        for (int j = 0; j < n; j++) {
            if (i >> j & 1) s += a[j];
            else s -= a[j];
            b[j + 1] = s;
        }
        sort(b, b + n + 1);
        ans = min(ans, (int)(unique(b, b + n + 1) - b));
    }
    printf("%d
", ans);
}
#include <bits/stdc++.h>
using namespace std;
int n, a[30], b[30], c, cnt, v[5000001], ans = 25;
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    for (int i = 0; i < (1 << n); i++) {
        int s = 25 * 100000;
        c++;
        cnt = 1;
        v[s] = c;
        for (int j = 0; j < n; j++) {
            if (i >> j & 1) s += a[j];
            else s -= a[j];
            if (v[s] != c) {
                cnt++;
                v[s] = c;
            }
        }
        ans=min(ans,cnt);
    }
    printf("%d
", ans);
}
#include <bits/stdc++.h>
using namespace std;
int n, a[30], b[30], c, cnt, v[5000001], ans = 25;
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    for (int i = 0; i < (1 << n); i+=2) {
        int s = 25 * 100000;
        c++;
        cnt = 1;
        v[s] = c;
        for (int j = 0; j < n; j++) {
            if (i >> j & 1) s += a[j];
            else s -= a[j];
            if (v[s] != c) {
                cnt++;
                v[s] = c;
            }
        }
        ans=min(ans,cnt);
    }
    printf("%d
", ans);
}
#include <bits/stdc++.h>
using namespace std;
const int SIZE = 5e6+10;
int m,cnt[SIZE],an,d[30];
void dfs(int i,int x,int v){
    if(i==m){
        an=min(an,v);
        return;
    }
    int nxt=x+d[i];
    cnt[nxt]++;
    dfs(i+1,nxt,v+(cnt[nxt]==1));
    cnt[nxt]--;

    nxt=x-d[i];
    cnt[nxt]++;
    dfs(i+1,nxt,v+(cnt[nxt]==1));
    cnt[nxt]--;
}
int main(){
    scanf("%d",&m);
    an=m+1;
    for(int i=0;i<m;i++)
        scanf("%d",&d[i]);
    cnt[SIZE/2]=1;//0
    cnt[SIZE/2+d[0]]=1;//强制第一步向右
    dfs(1,SIZE/2+d[0],2);
    printf("%d
",an);
    return 0;
}
原文地址:https://www.cnblogs.com/lqerio/p/9756910.html