[关闭]
@Acqua 2019-01-18T06:49:46.000000Z 字数 1970 阅读 1142

POJ1015 Jury Compromise(Jan. 18th, 2019) 背包方案输出

动态规划

题目来源

题意

给定一个元数对集合,从其中选择个,求的方案。若有多个答案,任意输出其中一个。

思路

  1. 处理出
  2. 背包式DP,完整路径更新(非指针)。
  3. 查找最小值。

代码

  1. // La Pluie
  2. #include<vector>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<iostream>
  6. #include<algorithm>
  7. using namespace std;
  8. const int N = 200 + 5, M = 20 + 5;
  9. struct PLUIE{
  10. int p/*lus*/, s/*ubtract*/, t/*otal*/, d/*ifference*/;
  11. } pluie[N];
  12. int n, m, res_p, res_s, ans[M], dp[M][N << 2];
  13. // dp[i][j] stands for the situation that i people are chosen and now the difference of the remark is j.
  14. vector <int> link[M][N << 2];
  15. void INPUT(){
  16. for(int i = 1; i <= n; i++){
  17. int a, b, c, d;
  18. scanf("%d %d", &a, &b);
  19. c = a + b, d = a - b;
  20. pluie[i] = (PLUIE){a, b, c, d};
  21. }
  22. }
  23. void DFS(int k){
  24. for(int i = 0; i < link[m][k]. size(); i++)
  25. ans[i + 1] = link[m][k][i];
  26. }
  27. void SOLVE(){
  28. res_p = res_s = 0;
  29. int mov = 20 * m;
  30. for(int i = 1; i <= m; i++)
  31. for(int j = 0; j <= (mov << 1); j++)
  32. link[i][j]. clear();
  33. memset(dp, -1, sizeof(dp));
  34. dp[0][mov] = 0;
  35. for(int i = 1; i <= n; i++){ // Come to confirm the next one when the present one has been confirmed.
  36. for(int j = m; j > 0; j--){ // As 01 Package
  37. for(int k = 0; k < (mov << 1); k++){
  38. int lune = k - pluie[i]. d; // The difference of the previous situation.
  39. // pluie[i]. d stands for the difference of choosing the i-th person minus not choosing him.
  40. if(lune >= 0 && dp[j - 1][lune] >= 0 && dp[j][k] < dp[j - 1][lune] + pluie[i]. t){
  41. dp[j][k] = dp[j - 1][lune] + pluie[i]. t;
  42. link[j][k] = link[j - 1][lune]; // Copy the path.
  43. link[j][k]. push_back(i); // Extend the path.
  44. }
  45. }
  46. }
  47. }
  48. for(int i = mov, j = mov; i >= 0; i--, j++){ // Equals to `for(int d = 0; d <= mov; d++) i = mov - d, j = mov + d` to search the one which is the closest to the zero point. Obviously, the first one found is the answer.
  49. if(dp[m][i] >= 0){
  50. if(dp[m][j] > dp[m][i]) DFS(j);
  51. else DFS(i);
  52. break;
  53. }
  54. if(dp[m][j] >= 0){
  55. DFS(j);
  56. break;
  57. }
  58. }
  59. for(int i = 1; i <= m; i++){
  60. res_p += pluie[ans[i]]. p;
  61. res_s += pluie[ans[i]]. s;
  62. }
  63. }
  64. void OUTPUT(int cnt){
  65. printf("Jury #%d\n", cnt);
  66. printf("Best jury has value %d for prosecution and value %d for defence:\n", res_p, res_s);
  67. for(int i = 1; i <= m; i++)
  68. printf(" %d", ans[i]);
  69. printf("\n\n");
  70. }
  71. int main(){
  72. int cnt = 0;
  73. while(~scanf("%d %d", &n, &m) && (n || m)){
  74. INPUT();
  75. SOLVE();
  76. OUTPUT(++cnt);
  77. }
  78. return 0;
  79. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注