[关闭]
@cww97 2018-04-23T05:16:25.000000Z 字数 3276 阅读 1014

all_dream 笔试

NOIP


by 陈伟文

1.求排列逆序数

思路:树状数组求逆序对

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. const int N = 1e5 + 7;
  5. struct binaryIndexTree{
  6. int val[N], n;
  7. inline void init(int n){
  8. this->n = n;
  9. memset(val, 0, sizeof(val));
  10. }
  11. inline void add(int k, int num){
  12. for (;k <= n; k += k&-k) val[k] += num;
  13. }
  14. int sum(int k){
  15. int sum = 0;
  16. for (; k; k -= k&-k) sum += val[k];
  17. return sum;
  18. }
  19. } T;
  20. int main(){
  21. //freopen("in.txt", "r", stdin);
  22. // 思路:树状数组求逆序对裸题
  23. for (int n; ~scanf("%d", &n);){
  24. T.init(n);
  25. LL sum = 0; // ans may larger than INT_MAX
  26. for (int x, i = 0; i < n; i++){
  27. scanf("%d", &x); // input
  28. sum += T.sum(n) - T.sum(x - 1); // sum[x..n]
  29. T.add(x, 1);
  30. }
  31. printf("%lld\n", sum);
  32. }
  33. }

2.装箱问题

思路:01背包

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N = 33;
  4. const int V = 2e4 + 7;
  5. int v[N]; // 每个箱子容量
  6. int f[N][V]; //
  7. int main(){
  8. //freopen("in.txt", "r", stdin);
  9. for (int cap, n; ~scanf("%d%d", &cap, &n);){
  10. for (int i = 1; i <= n; i++){
  11. scanf("%d", &v[i]); // just input
  12. }
  13. memset(f, 0, sizeof f);
  14. f[0][0] = true;
  15. for (int i = 1; i <= n; i++){
  16. for (int j = 0; j <= cap; j++){
  17. f[i][j] = f[i-1][j]; // ignore v[i]
  18. if (v[i] <= j){ // v[i] not too large
  19. f[i][j] |= f[i-1][j-v[i]]; // pack v[i]
  20. }
  21. }
  22. }
  23. int ans = 0;
  24. for (int i = 0; i <= cap; i++){
  25. if (f[n][i]) ans = i;
  26. }
  27. printf("%d\n", cap - ans);
  28. }
  29. return 0;
  30. }

3.仙岛求药

思路:bfs

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N = 22;
  4. const int dx[] = {-1, 1, 0, 0};
  5. const int dy[] = {0, 0, -1, 1};
  6. struct node{
  7. int x, y, step;
  8. node(){}
  9. node(int _x, int _y, int s):x(_x), y(_y),step(s){}
  10. };
  11. int m, n;
  12. int g[N][N]; // grid
  13. bool vis[N][N]; // visited
  14. inline int bfs(int sx, int sy, int tx, int ty){
  15. queue <node> Q;
  16. Q.push(node(sx, sy, 0));
  17. memset(vis, 0, sizeof(vis));
  18. vis[sx][sy] = true;
  19. for (; !Q.empty();){
  20. node now = Q.front(); Q.pop();
  21. if (now.x == tx && now.y == ty) return now.step;
  22. for (int i = 0; i < 4; i++){
  23. int cx = now.x + dx[i];
  24. int cy = now.y + dy[i]; // new position
  25. if (cx<1 || cx>m || cy<1 || cy>n) continue;
  26. if (vis[cx][cy] || g[cx][cy]) continue;
  27. vis[cx][cy] = true;
  28. Q.push(node(cx, cy, now.step+1));
  29. }
  30. }
  31. return -1;
  32. }
  33. int main(){
  34. //freopen("in.txt", "r", stdin);
  35. char st[N];
  36. for (int sx, sy, tx, ty; ~scanf("%d%d\n", &m, &n);){
  37. if (m == 0 && n == 0) break;
  38. for (int i = 1; i <= m; i++){
  39. scanf("%s\n", st);
  40. for (int j = 0; j < n; j++){
  41. if (st[j] == '#') g[i][j+1] = 1; // monster
  42. else{
  43. g[i][j+1] = 0; // can walk
  44. if (st[j] == '@') sx = i, sy = j + 1; // start x, y
  45. if (st[j] == '*') tx = i, ty = j + 1; // target x, y
  46. }
  47. }
  48. }
  49. int ans = bfs(sx, sy, tx, ty);
  50. printf("%d\n", ans);
  51. }
  52. return 0;
  53. }

4.画家问题

思路:枚举

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cmath>
  4. #include <algorithm>
  5. #include <cstdlib>
  6. using namespace std;
  7. const int N = 22;
  8. const int INF = 0x3f3f3f3f;
  9. int g[N][N], temp[N][N], row[N];
  10. int n, cnt;
  11. void meiju(int x){ // ugly name, sorry
  12. memset(row, 0, sizeof(row));
  13. for (int i = 0; x; x >>= 1) row[i++] = x&1;
  14. }
  15. void paint(int x,int y){
  16. temp[x][y] ^= 1;
  17. if (x-1 >= 0) temp[x-1][y] ^= 1;
  18. if (y-1 >= 0) temp[x][y-1] ^= 1;
  19. if (x+1 < n) temp[x+1][y] ^= 1;
  20. if (y+1 < n) temp[x][y+1] ^= 1;
  21. cnt++;
  22. }
  23. int check(){
  24. for(int i = 1; i < n; ++i){
  25. for(int j = 0; j < n; ++j){
  26. if(temp[i-1][j] != 1)paint(i,j);
  27. }
  28. }
  29. for(int i = 0; i < n; ++i){
  30. if(temp[n-1][i] != 1) return INF; //not all yello, failed
  31. }
  32. return cnt;
  33. }
  34. int main(){
  35. //freopen("in.txt", "r", stdin);
  36. int _;
  37. scanf("%d", &_);
  38. for (; _--;){
  39. scanf("%d", &n);
  40. int ans = INF;
  41. char s[16];
  42. for(int i = 0; i < n; ++i){ // just input
  43. scanf("%s", s);
  44. for(int j = 0; j < n; ++j){
  45. if (s[j] == 'w') g[i][j] = 0;
  46. else g[i][j] = 1;
  47. }
  48. }
  49. int k = pow(2.0, n);
  50. for(int i = 0; i < k; ++i){
  51. meiju(i);
  52. cnt = 0; // init
  53. memcpy(temp, g, sizeof g);
  54. for(int j = 0; j < n; ++j){
  55. if (row[j] == 1) paint(0, j);
  56. }
  57. ans = min(ans, check());
  58. }
  59. if (ans == INF) puts("inf");
  60. else printf("%d\n", ans);
  61. }
  62. return 0;
  63. }

5.全排列

思路:STL小练习

  1. #include <bits/stdc++.h>
  2. typedef long long LL;
  3. using namespace std;
  4. int a[] = {0, 1, 2, 3, 4, 5};
  5. int main(){
  6. string s;
  7. cin >> s;
  8. do{
  9. for (int i = 0; i < s.size(); i++){
  10. cout << s[a[i]];
  11. }
  12. puts("");
  13. }while(next_permutation(a, a+s.size()));
  14. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注