P1216 [USACO1.5] [IOI1994]数字三角形 Number Triangles
该题的思路是,从底层数开始,逐渐向上更新。
例如:
1
2 3
5 6 7
经过一次更新后,从倒数第二层开始,对于2,它的两个孩子5和6中6更大,于是2更新为2+6=8,同理3更新为10之后就有:
1
8 10
5 6 7
层数向上移动一层,接着从第一层继续执行上述操作,1+10=11,所以有:
11
8 10
5 6 7
输出第一个数就是最大路径和,1 + 3 + 7 = 11
很容易发现,每一次更新,把被更新的数变成由它向下辐射的三角中的,最大路径和。例如上例中的三角3 6 7, 3经过更新后变成三角3 6 7的最大路径和,3 + 7 = 10。采用这种分治的思想,从小到大,递归得到由第一个数向下辐射的三角的最大路径和。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include<iostream> #include<algorithm>
int f[500510]; int r, j;
int main(){ std::cin >> r; int cnt = r * (r + 1) / 2; for(int i = 1; i <= cnt; i++){ std::cin >> f[i]; } cnt -= r; for(int i = r - 1; i >= 1; i--){ j = i; cnt -= i; while(j > 0){ f[cnt + j] += std::max(f[cnt + j + i], f[cnt + j + i + 1]); j--; } } std::cout << f[1]; return 0; }
|
P1048 [NOIP2005 普及组] 采药
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include<iostream> #include<algorithm>
int f[1100] = {0};
int main(){ int time, num, t, value; std::cin >> time >> num; for(int i = 1; i <= num; i++){ std::cin >> t >> value; for(int j = time; j >= t; j--){ f[j] = std::max(f[j], f[j - t] + value); } } std::cout << f[time]; return 0; }
|
P2196 [NOIP1996 提高组] 挖地雷
有向无边权,有点权的图。
思路是,设置一个数组max,存储第 i 个节点前最大地雷和,同理于上述背包问题里的数组 f。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include<iostream> #include<algorithm>
int num, t, ans = 0; int f[100] = {0}, max[100] = {0}; int path[30][30] = {0}; int pre[30] = {0}; int sum = 0;
int main(){ std::cin >> num; for(int i = 1; i <= num; i++){ std::cin >> f[i]; } for(int i = 1; i <= num - 1; i++){ for(int j = i + 1;j <= num; j++){ std::cin >> path[i][j]; } } for(int i = 1; i <= num; i++){ for(int j = 1; j <= num; j++){ if(path[j][i] && max[j] > max[i]){ max[i] = max[j]; pre[i] = j; } } max[i] += f[i]; if(max[i] > ans){ ans = max[i]; t = i; } } int cnt = 1; for(int i = t; i != 0; i = pre[i], cnt++){ f[cnt] = i; } for(int i = cnt - 1; i >= 1; i--){ std::cout << f[i] << ' '; } std::cout << "\n"<< ans; return 0; }
|
P1434[SHOI2002] 滑雪
这是一道深度搜索问题,DFS。
通过遍历每个节点,然后往深处搜索最大路径,其中搜索过的路径会被数组f[] []记录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| #include<iostream> #include<algorithm>
int map[110][110] = {0}; int f[110][110] = {0}; int r, c, ans = 0; int dx[4] = {0, 0, 1, -1}; int dy[4] = {1, -1, 0, 0};
int dfs(int x, int y){ if(f[x][y]){} else{ f[x][y] = 1; for(int i = 0; i <4; i++){ int x0 = x + dx[i], y0 = y + dy[i]; if(x0 > 0 && y0 >0 && x0 <= r && y0 <= c){ if(map[x][y] > map[x0][y0]){ f[x][y] = std::max(f[x][y], dfs(x0, y0) + 1); } } } } return f[x][y]; }
int main(){ std::cin >> r >> c; for(int i = 1; i <= r; i++){ for(int j = 1; j <= c; j++){ std::cin >> map[i][j]; } } for(int i = 1; i <= r; i++){ for(int j = 1; j <= c; j++){ ans = std::max(ans, dfs(i, j)); } } std::cout << ans; return 0; }
|