• Dreamoon and MRT(二元枚举)


    题目

    数轴上有M个点a1、a2、...am,另有一个数列p1、p2、...pn,(1 ≤ pii ≤ M)。

    给定d1、d2、...dn,对所有的 i (1 ≤ i ≤ n),已知 |api+1 - api| = di,求M得最少可能值。(1 ≤ n ≤ 25 ,1 ≤ ai ≤ 105)

    原题链接:http://codeforces.com/group/gRkn7bDfsN/contest/212299/problem/B

    思路

    基本思路:枚举 api+1 在 api 的左边或右边,为了降低复杂度,强制第一次选向右(向左也可以)。

    思路一:利用二进制+位运算,枚举所有的可能

    O(2N-1N)

     1 #include<stdio.h>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 
     7 const int SIZE = (25 * 100000) * 2 + 100;  //数轴的范围
     8 const int maxn = 25 + 10;
     9 int n, d[maxn];
    10 int ans,cnt,vis[SIZE];
    11 
    12 void solve()
    13 {
    14     //对剩下m-1个选择进行枚举
    15     for (int i = 0; i < (1 << (n - 1)); i++)
    16     {
    17         int v_num = 2;
    18         cnt++;
    19         int s = SIZE / 2 + d[0];
    20         //for (int i = 0; i < SIZE; i++)  vis[i] = 0; //这种标记会导致T
    21         vis[SIZE / 2] = cnt;            
    22         vis[SIZE / 2 + d[0]] = cnt;        //强行规定第一次向左走
    23 
    24         for (int j = 0; j < n - 1; j++)
    25         {
    26             if (i & (1 << j))
    27                 s += d[j + 1];
    28             else
    29                 s -= d[j + 1];
    30             if (vis[s] != cnt) 
    31             {
    32                 v_num++;
    33                 vis[s] = cnt;
    34             }
    35         }
    36         ans = min(ans, v_num);
    37     }
    38 }
    39 
    40 int main()
    41 {
    42     scanf("%d", &n);
    43     for (int i = 0; i < n; i++)
    44         scanf("%d", &d[i]);
    45     ans = n + 1;               //ans不会超过n+1
    46     cnt = 0;
    47     solve();
    48     printf("%d
    ", ans);
    49     return 0;
    50 }

     思路二:DFS尝试遍每一种情况

    O(2N-1)

     1 #include<stdio.h>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 
     7 const int SIZE = 25 * 100000 * 2 + 10;    //数轴的范围,SIZE/2相当于原点
     8 const int maxn = 25 + 10;
     9 int m, d[maxn];
    10 int vis[SIZE];
    11 int ans;
    12 
    13 //第cur+1个状态,x位置,顶点数v
    14 void dfs(int cur, int x, int v)
    15 {
    16     if (cur == m)
    17     {
    18         ans = min(ans, v);
    19         return;
    20     }
    21     int net = x + d[cur];
    22     vis[net]++;        //不能只用0/1来区分
    23     dfs(cur + 1, net, v + (vis[net] == 1));
    24     vis[net]--;
    25 
    26     net = x - d[cur];
    27     vis[net]++;
    28     dfs(cur + 1, net, v + (vis[net] == 1));
    29     vis[net]--;
    30 }
    31 
    32 int main()
    33 {
    34     while (scanf("%d",&m) == 1 && m)
    35     {
    36         memset(vis, 0, sizeof(vis));
    37         for (int i = 0; i < m; i++)
    38             scanf("%d", &d[i]);
    39         ans = m + 1;            //ans不会超过m+1
    40         vis[SIZE / 2] = 1;
    41         vis[SIZE / 2 + d[0]] = 1;        //强行规定第一次向有走
    42         dfs(1, SIZE / 2 + d[0], 2);
    43         printf("%d
    ", ans);
    44     }
    45     return 0;
    46 }
  • 相关阅读:
    计算机硕士工资一览表 08年最新各大IT公司薪水行
    VS2010单元测试
    windows操作系统的快捷键
    关于
    [美国代购] Nexus 6 与 Moto X 询价聊天记录整理
    nginxのerror_logはformat指定できない.
    Give $20/month and provide 480 hours of free education
    如何才可能将一件事情做到最高的效率
    Palindrome Number
    Reverse Integer
  • 原文地址:https://www.cnblogs.com/lfri/p/9775832.html
Copyright © 2020-2023  润新知