[关闭]
@gzyqwq 2018-10-22T02:33:56.000000Z 字数 10614 阅读 619

DP已经做完的题目:

bzoj 1587

  1. //f[i][j]表示前i个位置,分了j段的最小值.
  2. // f[i][j] = f[l][j - 1] + a[i];
  3. // f[i][j] = min(f[l][j - 1] + sum[i] - sum[l - 1],f[i][j]);
  4. #include <iostream>
  5. #include <cstring>
  6. #include <cstdio>
  7. using namespace std;
  8. const int maxN = 1000 + 7;
  9. inline int read() {
  10. int x = 0,f = 1;char c = getchar();
  11. while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
  12. while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
  13. return x * f;
  14. }
  15. int f[maxN][15];//f[i][j]表示前i个东西分成j段的最小价值.
  16. int a[maxN];
  17. int sum[maxN][maxN];//sum[i][j]表示把[1,i - 1]移动到i的价值.
  18. int pre[maxN];
  19. int main() {
  20. // freopen("1.in","r",stdin);
  21. int n,k;
  22. memset(f,0x3f,sizeof(f));
  23. scanf("%d%d",&n,&k);
  24. for(int i = n;i >= 1;-- i)
  25. scanf("%d",&a[i]);
  26. for(int i = 0;i <= n;++ i) pre[i] = pre[i - 1] + a[i];
  27. for(int i = 0;i <= n;++ i)
  28. for(int j = i + 1;j <= n;++ j)
  29. sum[i][j] = sum[i][j - 1] + pre[j - 1] - pre[i - 1];
  30. f[0][0] = 0;
  31. for(int i = 1;i <= n;++ i) {
  32. int tmp = min(i,k);
  33. for(int j = 1;j <= tmp;++ j) {
  34. f[i][j] = f[i - 1][j - 1];
  35. for(int l = 0;l < i;++ l) {
  36. f[i][j] = min(f[i][j],f[l - 1][j - 1] + sum[l][i]);
  37. }
  38. }
  39. }
  40. printf("%d\n", f[n][k]);
  41. return 0;
  42. }

luogu 1423

  1. #include <iostream>
  2. #include <cstring>
  3. #include <cstdio>
  4. const int maxN = 100 + 7;
  5. #define rep(i,x,p) for(int i = x;i <= p;++ i)
  6. #define sep(i,x,p) for(int i = x;i >= p;-- i)
  7. const int gx[] = {0,0,0,1,-1};
  8. const int gy[] = {0,1,-1,0,0};
  9. int a[maxN][maxN];
  10. int f[maxN][maxN];// f[i][j]表示可以到达i行j列的最大步数
  11. int n,m;
  12. inline int read() {
  13. int x = 0,f = 1;char c = getchar();
  14. while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
  15. while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
  16. return x * f;
  17. }
  18. inline int max(int a,int b) {return a > b ? a : b;}
  19. int dfs(int x,int y) {
  20. if(x < 1 || y < 1 || x > n || y > m) return -1;
  21. if(f[x][y] != -1) return f[x][y];
  22. int tmp = 0;
  23. rep(i,1,4)
  24. if(a[x + gx[i]][y + gy[i]] < a[x][y])tmp = max( dfs(x + gx[i],y + gy[i]) + 1, tmp) ;
  25. f[x][y] = tmp;
  26. return tmp;
  27. }
  28. int main() {
  29. // freopen("1.in","r",stdin);
  30. n = read();m = read();
  31. memset(f,-1,sizeof(f));
  32. rep(i,1,n)
  33. rep(j,1,m)
  34. a[i][j] = read();
  35. rep(i,1,n)
  36. rep(j,1,m)
  37. if(f[i][j] == -1) f[i][j] = dfs(i,j);
  38. int maxx = 0;
  39. rep(i,1,n)
  40. rep(j,1,n)
  41. maxx = max(maxx,f[i][j] + 1);
  42. printf("%d\n", maxx);
  43. return 0;
  44. }

bzoj 3208

  1. #include <iostream>
  2. #include <cstdio>
  3. #define rep(i,x,p) for(int i = x;i <= p;++ i)
  4. #define sep(i,x,p) for(int i = x;i >= p;-- i)
  5. const int maxN = 700 + 7;
  6. const int gx[] = {0,0,0,1,-1};
  7. const int gy[] = {0,1,-1,0,0};
  8. int a[maxN][maxN],n,m,f[maxN][maxN];
  9. bool vis[maxN][maxN]; //是否可以移动到这...
  10. char s[2];
  11. inline int read() {
  12. int x = 0,f = 1;char c = getchar();
  13. while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
  14. while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
  15. return x * f;
  16. }
  17. inline int max(int a,int b) {return a > b ? a : b;}
  18. inline int min(int a,int b) {return a > b ? b : a;}
  19. void work_1() {
  20. int x,y,z;
  21. x = read();y = read();z = read();
  22. a[x][y] = z;
  23. return;
  24. }
  25. void work_2() {
  26. int x1 = read(),y1 = read(),x2 = read(),y2 = read();
  27. rep(i,x1,x2)
  28. rep(j,y1,y2)
  29. vis[i][j] = true;
  30. return;
  31. }
  32. void work_3() {
  33. int x1 = read(),y1 = read(),x2 = read(),y2 = read();
  34. rep(i,x1,x2)
  35. rep(j,y1,y2)
  36. vis[i][j] = false;
  37. }
  38. int dfs(int x,int y) {
  39. if(x < 1 || y < 1 || x > n || y > n || vis[x][y]) return -1;
  40. if(f[x][y] != -1) return f[x][y];
  41. int tmp = 0;
  42. rep(i,1,4)
  43. if(a[x + gx[i]][y + gy[i]] < a[x][y])tmp = max( dfs(x + gx[i],y + gy[i]) + 1, tmp) ;
  44. f[x][y] = tmp;
  45. return tmp;
  46. }
  47. void work_4() {
  48. rep(i,1,n)
  49. rep(j,1,n)
  50. f[i][j] = -1;
  51. rep(i,1,n)
  52. rep(j,1,n)
  53. if(f[i][j] == -1) f[i][j] = dfs(i,j);
  54. int maxx = 0;
  55. rep(i,1,n)
  56. rep(j,1,n)
  57. maxx = max(maxx,f[i][j] + 1);
  58. printf("%d\n", maxx);
  59. }
  60. int main()
  61. {
  62. n = read();
  63. rep(i,1,n)
  64. rep(j,1,n)
  65. a[i][j] = read();
  66. m = read();
  67. while(m --) {
  68. scanf("%s",&s);
  69. if(s[0] == 'C') work_1();
  70. if(s[0] == 'S') work_2();
  71. if(s[0] == 'B') work_3();
  72. if(s[0] == 'Q') work_4();
  73. }
  74. return 0;
  75. }
  76. /*
  77. 并给出m个命令,
  78. C a b c表示坐标为a,b的点的高度改为c;
  79. S a b c d表示左上角为a,b右下角为c,d的矩形地区开始进行保护,
  80. 即不能继续滑雪;
  81. B a b c d表示左上角为a b,右下角为c d的矩形地区取消保护,
  82. 即可以开始滑雪;
  83. Q表示询问现在该风景区可以滑雪的最长路径为多少。对于每个Q要作一次回答。
  84. */

bzoj 1596

  1. #include <iostream>
  2. #include <cstdio>
  3. #define rep(i,x,p) for(int i = x;i <= p;++ i)
  4. #define sep(i,x,p) for(int i = x;i >= p;-- i)
  5. const int maxN = 10000 + 7;
  6. const int inf = 0x3f3f3f3f;
  7. using namespace std;
  8. inline int read() {
  9. int x = 0,f = 1;char c = getchar();
  10. while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
  11. while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
  12. return x * f;
  13. }
  14. int f[maxN][3];
  15. struct Node{
  16. int v,nex;
  17. }Map[maxN << 1];
  18. int num,head[maxN];
  19. inline void add_Node(int u,int v) {
  20. Map[++ num].v = v;
  21. Map[num].nex = head[u];
  22. head[u] = num;
  23. }
  24. void dfs(int now,int fa) {
  25. bool flag = false;
  26. for(int i = head[now];i;i = Map[i].nex) {
  27. int v = Map[i].v;
  28. if(v == fa) continue;
  29. dfs(v,now);
  30. flag = true;
  31. }
  32. if(flag == false) {
  33. f[now][0] = inf;
  34. f[now][1] = 1;
  35. f[now][2] = 0;
  36. return;
  37. }
  38. f[now][1] = 1;
  39. int tmp_min = inf;
  40. bool is_ok = true;
  41. for(int i = head[now];i;i = Map[i].nex) {
  42. int v = Map[i].v;
  43. if(v == fa) continue;
  44. f[now][1] += min(f[v][1] , min ( f[v][0] , f[v][2] ) );
  45. f[now][2] += min( f[v][0] , f[v][1] );
  46. tmp_min = min( f[v][1] - f[v][0] , tmp_min);
  47. if(f[v][1] <= f[v][0]) {
  48. is_ok = false;
  49. f[now][0] += f[v][1];
  50. }
  51. else f[now][0] += f[v][0];
  52. }
  53. if(is_ok) f[now][0] += tmp_min;
  54. return ;
  55. }
  56. int main()
  57. {
  58. // freopen("1.in","r",stdin);
  59. int n,u,v;
  60. n = read();
  61. for(int i = 1;i < n;++ i){
  62. u = read();v = read();
  63. add_Node(u,v);
  64. add_Node(v,u);
  65. }
  66. dfs(1,1);
  67. printf("%d\n", min(f[1][0] , f[1][1]));
  68. return 0;
  69. }
  70. //f[i][0]表示以i为根的子树,最少建造的无线电个数,i点被其儿子覆盖
  71. //f[i][1]表示以i为根的子树,最少建造的无线电个数,i点被自己覆盖
  72. //f[i][2]表示以i为根的子树,最少建造的无线电个数,i点被其父亲覆盖
  73. //f[i][0] = min( )
  74. //转移方程:
  75. //f[i][0] += f[v][0] , f[v][1] ) ;//一定要有一个.这个真麻烦....无语...莫名无语...
  76. //f[i][1] += min (f[v][2] , f[v][0], f[v][1]) + 1;
  77. //f[i][2] += min ( f[v][0], f[v][1] );

Bzoj 1827

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #define rep(i,x,p) for(re int i = x;i <= p;++ i)
  5. #define sep(i,x,p) for(re int i = x;i >= p;-- i)
  6. using namespace std;
  7. #define ll long long
  8. #define re register
  9. const int maxN = 100000 + 7;
  10. struct Node {
  11. int v,nex;
  12. int w;
  13. }Map[maxN << 1];
  14. int num,head[maxN];
  15. inline int read() {
  16. int x = 0 ,f = 1;char c = getchar();
  17. while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
  18. while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
  19. return x * f;
  20. }
  21. inline void add_Node(int u,int v,int w) {
  22. Map[++ num] = (Node) {v,head[u],w};
  23. head[u] = num;
  24. return;
  25. }
  26. ll f[maxN];
  27. ll D[maxN];
  28. ll Q[maxN];
  29. // f[v] = f[u] + (sum - 2 * D[i]) * w[i];
  30. // D[u] = \sum D[v] + c[u]
  31. // Q[u] = \sum Q[v] + \sum( D[v] * w[i])
  32. void dfs_1(int now,int fa) {
  33. for(int i = head[now];i;i = Map[i].nex) {
  34. int v = Map[i].v,w = Map[i].w;
  35. if(v != fa) {
  36. dfs_1(v,now);
  37. D[now] += D[v];
  38. Q[now] = Q[now] + Q[v] + D[v] * w;
  39. }
  40. }
  41. return;
  42. }
  43. void dfs_2(int now,int fa) {
  44. for(int i = head[now];i;i = Map[i].nex) {
  45. int v = Map[i].v,w = Map[i].w;
  46. if(v != fa) {
  47. f[v] = f[now] + (D[1] - 2 * D[v]) * w;
  48. dfs_2(v,now);
  49. }
  50. }
  51. }
  52. int main() {
  53. // freopen("1.in","r",stdin);
  54. int n = read(),u,v,w;
  55. rep(i,1,n) D[i] = read();
  56. rep(i,1,n - 1) {
  57. u = read();v = read();w = read();
  58. add_Node(u,v,w);
  59. add_Node(v,u,w);
  60. }
  61. dfs_1(1,1);
  62. f[1] = Q[1];
  63. dfs_2(1,1);
  64. ll ans = 1e12;
  65. rep(i,1,n) ans = min(ans,f[i]);
  66. printf("%lld\n", ans);
  67. return 0;
  68. }

bzoj 1037

  1. #include <iostream>
  2. #include <cstdio>
  3. const int maxN = 150 + 7;
  4. const int maxM = 20 + 7;
  5. #define rep(i,x,p) for(int i = x;i <= p;++ i)
  6. const int mod = 12345678;
  7. int f[303][153][23][23];//f[i][j][l][k]表示前i个人,有j个男生.l表示以i为后缀的男生-女生的最大值,
  8. //k表示以i为后缀的女生-男生的最大值,
  9. inline int max(int a,int b) {return a > b ? a : b;}
  10. int main() {
  11. f[0][0][0][0] = 1;
  12. int n,m,k;
  13. scanf("%d%d%d",&n,&m,&k);
  14. rep(i,0,n + m - 1)
  15. rep(j,0,n)
  16. rep(x,0,k)
  17. rep(y,0,k)
  18. if(f[i][j][x][y]) {
  19. if(j + 1 <= n && x + 1 <= k) f[i + 1][j + 1][x + 1][max(y - 1,0)] = (f[i + 1][j + 1][x + 1][max(y - 1,0)] + f[i][j][x][y] ) % mod;
  20. if(i + 1 - j <= m && y + 1 <= k) f[i + 1][j][max(x - 1,0)][y + 1] = f[i + 1][j][max(x - 1,0)][y + 1] + f[i][j][x][y] % mod;
  21. }
  22. int ans = 0;
  23. rep(i,0,k)
  24. rep(j,0,k)
  25. ans = (ans + f[n + m][n][i][j]) % mod;
  26. printf("%d\n",ans);
  27. return 0;
  28. }
  29. 

bzoj 2037

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <cstring>
  4. #include <cstdio>
  5. using namespace std;
  6. const int maxN = 1000 + 7;
  7. int f[maxN][maxN][2];
  8. int sum[maxN][maxN],tmp_sum;
  9. struct Node {
  10. int x,y,w;
  11. }Map[maxN];
  12. inline int read() {
  13. int x = 0,f = 1;char c = getchar();
  14. while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
  15. while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
  16. return x * f;
  17. }
  18. bool cmp(Node a,Node b) {
  19. return a.x < b.x;
  20. }
  21. main() {
  22. int n,c,id;
  23. n = read();c = read();
  24. Map[n + 1].x = c;
  25. for(int i = 1;i <= n;++ i)
  26. scanf("%d",&Map[i].x);
  27. for(int i = 1;i <= n;++ i)
  28. scanf("%d",&Map[i].y);
  29. for(int i = 1;i <= n;++ i)
  30. scanf("%d",&Map[i].w),tmp_sum += Map[i].w;
  31. sort(Map + 1,Map + n + 2,cmp);
  32. for(int i = 1;i <= n + 1;++ i) {
  33. if(c == Map[i].x) id = i;
  34. }
  35. for(int i = 1;i <= n + 1;++ i)
  36. for(int j = i;j <= n + 1;++ j)
  37. sum[i][j] = sum[i][j - 1] + Map[j].w;
  38. for(int i = 1;i <= n + 1;++ i)
  39. for(int j = i;j <= n + 1;++ j)
  40. sum[i][j] = tmp_sum - sum[i][j];
  41. memset(f,-0x3f,sizeof(f));
  42. f[id][id][1] = f[id][id][0] = 0;
  43. for(int len = 1;len <= n;++ len) {
  44. for(int l = 1;l + len <= n + 1;++ l) {
  45. int r = l + len;
  46. f[l][r][0] = Map[l].y + max( f[l + 1][r][0] - (Map[l + 1].x - Map[l].x) * sum[l + 1][r] ,f[l + 1][r][1] - ( Map[r].x - Map[l].x ) * sum[l + 1][r]);
  47. f[l][r][1] = Map[r].y + max( f[l][r - 1][1] - (Map[r].x - Map[r - 1].x) * sum[l][r - 1] ,f[l][r - 1][0] - ( Map[r].x - Map[l].x ) * sum[l][r - 1]);
  48. }
  49. }
  50. printf("%.3lf\n", max(f[1][n + 1][1] , f[1][n + 1][0]) / 1000.0);
  51. return 0;
  52. }

luogu 1220

  1. #include <iostream>
  2. #include <cstring>
  3. #include <cstdio>
  4. using namespace std;
  5. #define int long long
  6. const int maxN = 1000 + 7;
  7. int f[maxN][maxN][2]; //f[i][j][k]表示i到j区间关闭路灯的最小功耗 k:0在左边 1在右边.
  8. int sum[maxN][maxN],tmp_sum;
  9. struct Node {
  10. int pos;
  11. int w;
  12. }Map[maxN];
  13. inline int read() {
  14. int x = 0,f = 1;char c = getchar();
  15. while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
  16. while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
  17. return x * f;
  18. }
  19. main() {
  20. int n,c;
  21. n = read();c = read();
  22. for(int i = 1;i <= n;++ i)
  23. scanf("%d%lld",&Map[i].pos,&Map[i].w),tmp_sum += Map[i].w;
  24. for(int i = 1;i <= n;++ i)
  25. for(int j = i;j <= n;++ j)
  26. sum[i][j] = sum[i][j - 1] + Map[j].w;
  27. for(int i = 1;i <= n;++ i)
  28. for(int j = i;j <= n;++ j)
  29. sum[i][j] = tmp_sum - sum[i][j];
  30. memset(f,1,sizeof(f));
  31. f[c][c][1] = f[c][c][0] = 0;
  32. for(int len = 1;len < n;++ len) {
  33. for(int l = 1;l + len<= n;++ l) {
  34. int r = l + len;
  35. f[l][r][0] = min( f[l + 1][r][0] + (Map[l + 1].pos - Map[l].pos) * sum[l + 1][r] ,f[l + 1][r][1] + ( Map[r].pos - Map[l].pos ) * sum[l + 1][r]);
  36. f[l][r][1] = min( f[l][r - 1][1] + (Map[r].pos - Map[r - 1].pos) * sum[l][r - 1] ,f[l][r - 1][0] + ( Map[r].pos - Map[l].pos ) * sum[l][r - 1]);
  37. }
  38. }
  39. printf("%lld\n", min(f[1][n][1] , f[1][n][0]));
  40. return 0;
  41. }

bzoj4033

  1. /*
  2. 边一侧的黑节点数*另一侧的黑节点数*边权+一侧的白节点数*另一侧的白节点数*边权
  3. */
  4. #include <iostream>
  5. #include <cstdio>
  6. #define rep(i,x,p) for(int i = x;i <= p;++ i)
  7. #define sep(i,x,p) for(int i = x;i >= p;-- i)
  8. #define int long long
  9. const int maxN = 2000 + 7;
  10. struct Node {
  11. int v,nex,w;
  12. }Map[maxN << 1];
  13. int f[maxN][maxN];
  14. int head[maxN],num;
  15. int size[maxN];
  16. inline int read() {
  17. int x = 0,f = 1;char c = getchar();
  18. while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
  19. while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
  20. return x * f;
  21. }
  22. void add_Node(int u,int v,int w) {
  23. Map[++ num] = (Node) {v,head[u],w};
  24. head[u] = num;
  25. return;
  26. }
  27. int n,k;
  28. inline int max(int a,int b) {return a > b ? a : b;}
  29. int calc(int val,int num,int x)//计算这条边的贡献
  30. {
  31. val=val * x * (k - x) + val * (num - x) * (n - k - (num - x));
  32. return val;
  33. }
  34. void DP(int now,int fa) {
  35. size[now] = 1;
  36. for(int i = head[now];i;i = Map[i].nex) {
  37. int v = Map[i].v;
  38. if(v == fa) continue;
  39. DP(v,now);
  40. sep(j , size[now], 0) {
  41. sep(l , size[v], 0) {
  42. int tmp = f[now][j] + f[v][l] + calc(Map[i].w,size[v],l);
  43. f[now][j + l] = max(f[now][j + l] , tmp);
  44. }
  45. }
  46. size[now] += size[v];
  47. }
  48. }
  49. #undef int
  50. int main() {
  51. #define int long long
  52. scanf("%lld%lld",&n,&k);
  53. int u , v, w;
  54. rep(i,1,n - 1) {
  55. u = read();v = read();w = read();
  56. add_Node(u,v,w);
  57. add_Node(v,u,w);
  58. }
  59. DP(1,1);
  60. printf("%lld\n", f[1][k]);
  61. return 0;
  62. }

luogu 3174

bzoj 1260

  1. /*
  2. 卡常记录: 28ms -> 30ms ?????
  3. 反过来考虑
  4. f[i][j]表示i~j被染色的最小次数.
  5. 分为三种情况考虑:
  6. 1.l == r f[l][r] = 1;
  7. 2.s[l] == s[r] f[l][r] = min(f[i + 1][r] , f[l][r - 1])
  8. 3.不满足上述条件的话.
  9. 枚举断点即可.
  10. */
  11. #include <iostream>
  12. #include <cstring>
  13. #include <cstring>
  14. #include <cstdio>
  15. #define rep(i,x,p) for(register int i = x;i <= p;++ i)
  16. #define sep(i,x,p) for(register int i = x;i >= p;-- i)
  17. const int maxN = 50 + 7;
  18. using namespace std;
  19. char s[maxN];
  20. int f[maxN][maxN];
  21. int main() {
  22. scanf("%s",s + 1);
  23. int n = strlen(s + 1);
  24. memset(f,0x3f,sizeof(f));
  25. rep(i,1,n) f[i][i] = 1;
  26. rep(len,1,n - 1) {
  27. for(register int l = 1;l + len <= n;++ l){
  28. int r = l + len;
  29. if(s[l] == s[r]) f[l][r] = min(f[l + 1][r] , f[l][r - 1]);
  30. rep(k , l ,r - 1) f[l][r] = min(f[l][k] + f[k + 1][r],f[l][r]);
  31. }
  32. }
  33. printf("%d", f[1][n]);
  34. return 0;
  35. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注