bupt summer training for 16 #7 ——搜索与DP

https://vjudge.net/contest/174962#overview

 

A.我们发现重点在于x,y只要累加就ok了

在每个x上只有上下两种状态,所以可以记忆化搜索

f[0/1][i]表示 x = i 时向下/上走,那需要移动多少才能走出去

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 const int maxn = 500010;
 7 
 8 typedef long long ll;
 9 
10 ll a[maxn], f[2][maxn];
11 
12 int n, b[2][maxn], vis[2][maxn];
13 
14 ll dfs(int i, int k, ll d = 0) {
15     if(vis[k][i]) {
16         b[k][i] = -1;
17         return f[k][i] = 0;
18     }
19     vis[k][i] = 1;
20     if(!f[k][i]) {
21         int y = i + (k ? a[i] : -a[i]);
22         if(y > n || y <= 1) d = 0;
23         else d = dfs(y, k ^ 1);
24         f[k][i] = d + a[i];
25         if(y >= 1 && y <= n && b[k ^ 1][y]) b[k][i] = -1;
26     }
27     vis[k][i] = 0;
28     return f[k][i];
29 }
30 
31 int main() {
32     scanf("%d", &n);
33     for(int i = 2;i <= n;i ++)
34         scanf("%I64d", &a[i]);
35     b[0][1] = b[1][1] = -1;
36     for(int i = 2;i <= n;i ++)
37         dfs(i, 0), dfs(i, 1);
38     for(int i = 1;i < n;i ++) {
39         if(b[0][1 + i]) puts("-1");
40         else printf("%I64d\n", i + f[0][1 + i]);
41     }
42     return 0;
43 }
View Code

写狗了又RE又T又WA的...写的丑陋,我。无法忍受

 

B.非常无脑的爆搜,效率玄学

数据范围个位数还是可以大胆以下的

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 const int xx[] = {-1, 1, 0, 0};
 7 const int yy[] = {0, 0, 1, -1};
 8 
 9 int n, m, k;
10 
11 char s[10][10];
12 
13 bool vis[10][10];
14 
15 bool dfs(const int &x, const int &y, const int &cc) {
16     if(cc == k) return 1;
17     int nx, ny;
18     for(int i = 0;i < 4;i ++) {
19         nx = x + xx[i], ny = y + yy[i];
20         if(nx > 0 && nx <= n && ny > 0 && ny <= m && s[nx][ny] != 'S' && !vis[nx][ny]) {
21             vis[nx][ny] = 1;
22             if(dfs(nx, ny, cc + 1)) return 1;
23             vis[nx][ny] = 0;
24         }
25     }
26     return 0;
27 }
28 
29 int main() {
30     while(scanf("%d %d", &n, &m), n!= 0) {
31         k = 0;
32         for(int i = 1;i <= n;i ++) {
33             scanf("%s", s[i] + 1);
34             for(int j = 1;j <= m;j ++)
35                 vis[i][j] = 0, k += (s[i][j] != 'S');
36         }
37         vis[1][1] = 1;
38         puts(dfs(1, 1, 1) ? "YES" : "NO");
39     }
40     return 0;
41 }
View Code

 

C.显而易见的树型DP,依旧写的很糟...

f[i][j]表示从节点 i 向下走距离 j 能获得的最大价值

 1 #include <cstdio>
 2 #include <vector>
 3 #include <cstring>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 
 8 int n, m, s, a[110], f[110][110], g[110][110];
 9 
10 vector <pair<int,int> > e[110];
11 
12 void dfs(int u, int fa) {
13     int v, w, i;
14     for(i = 0;i <= m;i ++) g[u][i] = 0;
15     for(i = 0;i < e[u].size();i ++) {
16         v = e[u][i].first;
17         if(v == fa) continue;
18         w = e[u][i].second;
19         dfs(v, u);
20         for(int j = m;j >= 0;j --)
21             for(int k = j;k >= 0;k --)
22                 if(j - k - w >= 0) 
23                     f[u][j] = max(f[u][j], g[u][k] + f[v][j - k - w]);
24         for(int j = 0;j <= m;j ++)
25             g[u][j] = f[u][j];
26     }
27     for(i = 0;i <= m;i ++) f[u][i] += a[u];
28 }
29 
30 int main() {
31     while(~scanf("%d", &n)) {
32         memset(f, 0, sizeof f);
33         memset(g, 0, sizeof g);
34         memset(e, 0, sizeof e);
35         for(int i = 1;i <= n;i ++)
36             scanf("%d", &a[i]);
37         for(int u, v, w, i = 1;i < n;i ++) {
38             scanf("%d %d %d", &u, &v, &w);
39             e[u].push_back(make_pair(v, w));
40             e[v].push_back(make_pair(u, w));
41         }
42         scanf("%d %d", &s, &m), m /= 2;
43         dfs(s, s);
44         printf("%d\n", f[s][m]);
45     }
46     return 0;
47 }
View Code

 

D.大家都会写大龙虾算法让我有些惶恐...

于是决定抄一发队友的dlx板子

posted @ 2017-07-31 21:34  ztztyyy  阅读(145)  评论(0编辑  收藏  举报