码迷,mamicode.com
首页 > 其他好文 > 详细

Dreamoon and MRT(二元枚举)

时间:2018-10-12 01:16:05      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:复杂   pac   .com   选择   题目   group   def   stream   name   

题目

数轴上有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 的左边或右边,为了降低复杂度,强制第一次选向右(向左也可以)。

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

 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\n", ans);
49     return 0;
50 }

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

 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\n", ans);
44     }
45     return 0;
46 }

 

Dreamoon and MRT(二元枚举)

标签:复杂   pac   .com   选择   题目   group   def   stream   name   

原文地址:https://www.cnblogs.com/lfri/p/9775832.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!