题目
数轴上有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 }