HDU 1074 Doing Homework

举报
Linux猿 发表于 2021/08/05 00:14:42 2021/08/05
【摘要】 题目链接~~> 做题感悟:这题以前看过但是没做出来,也不知道用状态压缩,今天做了一下竟然1A ,悲剧的是AC 之后我看别人都没排序,so~>自己也罢排序的删掉结果就wa了,这是为什么??? 解题思路:状态压缩 + 记忆化搜索                dp[ S ] 代表达到...

题目链接~~>

做题感悟:这题以前看过但是没做出来,也不知道用状态压缩,今天做了一下竟然1A ,悲剧的是AC 之后我看别人都没排序,so~>自己也罢排序的删掉结果就wa了,这是为什么???

解题思路:状态压缩 + 记忆化搜索

               dp[ S ] 代表达到状态 S 所减少的分数,其中S中的每一位代表某项作业到达状态 S 该作业已经做过。那么 dp[ S ] = min { dp [ S^(1<<i) ] + mx } ( 0 <= i < n  ,mx 只加上i后减少的分数)  ,还要开一个数组记录结束的天数,这里到达同一种状态所用的总天数是一样的。然后记忆化搜索就ok 了 。这里有一点不明白的是:问什么我不排序就wa,难道这靠人品吗抓狂??求指教??

代码:


  
  1. #include<iostream>
  2. #include<sstream>
  3. #include<map>
  4. #include<cmath>
  5. #include<fstream>
  6. #include<vector>
  7. #include<sstream>
  8. #include<cstring>
  9. #include<cstdio>
  10. #include<stack>
  11. #include<queue>
  12. #include<bitset>
  13. #include<ctime>
  14. #include<string>
  15. #include<iomanip>
  16. #include<algorithm>
  17. using namespace std ;
  18. #define INT long long int
  19. const int INF = 0x3f3f3f3f ;
  20. const double esp = 0.00000001 ;
  21. const double PI = acos(-1.0) ;
  22. const int mod = 6 ;
  23. const int MY = 8 ;
  24. const int MX = 50000 + 5 ;
  25. int n ;
  26. int pre[MX] ;
  27. int dp[MX] ,day[MX] ,pt[MX] ;
  28. struct node
  29. {
  30. char s[105] ;
  31. int x ,y ;
  32. }T[MX] ;
  33. bool cmp(node a ,node b)
  34. {
  35. return strcmp(a.s ,b.s) > 0 ;
  36. }
  37. void input()
  38. {
  39. scanf("%d" ,&n) ;
  40. memset(dp ,-1 ,sizeof(dp)) ;
  41. dp[0] = day[0] = pre[0] = 0 ;
  42. for(int i = 0 ;i < n ; ++i)
  43. {
  44. scanf("%s%d%d" ,T[i].s ,&T[i].x ,&T[i].y) ;
  45. pre[1<<i] =1<<i ;
  46. }
  47. sort(T ,T+n ,cmp) ; // 排序
  48. }
  49. int DP(int S) // 记忆化搜索
  50. {
  51. if(dp[S] != -1) return dp[S] ;
  52. int& ans = dp[S] ;
  53. ans = day[S] = INF ;
  54. int temp ,d ,cost ,end ;
  55. for(int i = 0 ;i < n ; ++i)
  56. if((S&(1<<i)))
  57. {
  58. temp = DP(S^(1<<i)) ;
  59. d = day[S^(1<<i)] ;
  60. end = d + T[i].y ;
  61. if(T[i].x <= d)
  62. cost = d-T[i].x + T[i].y ;
  63. else
  64. {
  65. if(T[i].x-d >= T[i].y)
  66. cost = 0 ;
  67. else
  68. cost = T[i].y - T[i].x + d ;
  69. }
  70. if(ans > temp + cost)
  71. {
  72. ans = temp+cost ;
  73. day[S] = end ;
  74. pre[S] = S^(1<<i) ;
  75. }
  76. }
  77. return ans ;
  78. }
  79. void print(int S) // 递归输出
  80. {
  81. if(pre[S] != S)
  82. {
  83. print(pre[S]) ;
  84. cout<<T[pt[pre[S]^S]].s<<endl ;
  85. }
  86. else return ;
  87. }
  88. void init()
  89. {
  90. for(int i = 0 ;i < 15 ; ++i)
  91. pt[1<<i] = i ;
  92. }
  93. int main()
  94. {
  95. init() ;
  96. int Tx ;
  97. scanf("%d" ,&Tx) ;
  98. while(Tx--)
  99. {
  100. input() ;
  101. cout<<DP((1<<n)-1)<<endl ;
  102. print((1<<n)-1) ;
  103. }
  104. return 0 ;
  105. }

HDU 1789 Doing Homework again

解题思路:这题意思和上面一题差不多,改变了一点就可以用贪心解决。

方法一、对截至时间排序,如果时间相等则价值从大到小排。

            需要用一个数记录已经写了几天了,因为时间是排好序的,如果处理到第 i 个,如果第 i 个的截至时间小于前面的累计时间那么记录天数加一就可以。如果第 i 个的截至时间大于等于前面累计的时间,就在前面找一个价值最小的且没被标记的任务标记,等于替换了最小的价值的任务,这样最终的结果为标记了的任务的价值。

方法二、对价值排序,如果价值相等时间从小到达排。

           价值从大到小排序,如果当前处理第 i 个任务,则从当前任务的截至时间开始往前找,看那一天没有被标记过,如果没有找到就应该加到最终的结果中,尽量选择靠近截止时间的那天做当前作业。

代码(方法一):


  
  1. #include<iostream>
  2. #include<sstream>
  3. #include<map>
  4. #include<cmath>
  5. #include<fstream>
  6. #include<vector>
  7. #include<sstream>
  8. #include<cstring>
  9. #include<cstdio>
  10. #include<stack>
  11. #include<queue>
  12. #include<bitset>
  13. #include<ctime>
  14. #include<string>
  15. #include<iomanip>
  16. #include<algorithm>
  17. using namespace std ;
  18. #define INT long long int
  19. const int INF = 0x3f3f3f3f ;
  20. const double esp = 0.00000001 ;
  21. const double PI = acos(-1.0) ;
  22. const int mod = 6 ;
  23. const int MY = 8 ;
  24. const int MX = 1000 + 5 ;
  25. int n ;
  26. bool vis[MX] ;
  27. struct node
  28. {
  29. int x ,y ;
  30. }T[MX] ;
  31. bool cmp(node a ,node b)
  32. {
  33. if(a.x != b.x)
  34. return a.x < b.x ;
  35. else return a.y > b.y ;
  36. }
  37. void input()
  38. {
  39. scanf("%d" ,&n) ;
  40. for(int i = 1 ;i <= n ; ++i)
  41. scanf("%d" ,&T[i].x) ;
  42. for(int i = 1 ;i <= n ; ++i)
  43. scanf("%d" ,&T[i].y) ;
  44. sort(T+1 ,T+n+1 ,cmp) ;
  45. }
  46. void solve()
  47. {
  48. memset(vis ,false ,sizeof(vis)) ;
  49. int num = 0 ,ans = 0 ;
  50. for(int i = 1 ;i <= n ; ++i)
  51. {
  52. if(num < T[i].x)
  53. num++ ;
  54. else
  55. {
  56. int flag = i ,Max = T[i].y ;
  57. for(int j = 1 ;j < i ; ++j)
  58. if(!vis[j] && T[j].y < Max) // 如果没被标记
  59. {
  60. Max = T[j].y ;
  61. flag = j ;
  62. }
  63. if(flag == i)
  64. {
  65. vis[i] = true ;
  66. ans += T[i].y ;
  67. }
  68. else
  69. {
  70. vis[flag] = true ;
  71. ans += Max ;
  72. }
  73. }
  74. }
  75. cout<<ans<<endl ;
  76. }
  77. int main()
  78. {
  79. int Tx ;
  80. scanf("%d" ,&Tx) ;
  81. while(Tx--)
  82. {
  83. input() ;
  84. solve() ;
  85. }
  86. return 0 ;
  87. }
代码(方法二):


  
  1. #include<iostream>
  2. #include<sstream>
  3. #include<map>
  4. #include<cmath>
  5. #include<fstream>
  6. #include<vector>
  7. #include<sstream>
  8. #include<cstring>
  9. #include<cstdio>
  10. #include<stack>
  11. #include<queue>
  12. #include<bitset>
  13. #include<ctime>
  14. #include<string>
  15. #include<iomanip>
  16. #include<algorithm>
  17. using namespace std ;
  18. #define INT long long int
  19. const int INF = 0x3f3f3f3f ;
  20. const double esp = 0.00000001 ;
  21. const double PI = acos(-1.0) ;
  22. const int mod = 6 ;
  23. const int MY = 8 ;
  24. const int MX = 1000 + 5 ;
  25. int n ;
  26. bool vis[MX] ;
  27. struct node
  28. {
  29. int x ,y ;
  30. }T[MX] ;
  31. bool cmp(node a ,node b)
  32. {
  33. if(a.y != b.y)
  34. return a.y > b.y ;
  35. else return a.x < b.x ;
  36. }
  37. void input()
  38. {
  39. scanf("%d" ,&n) ;
  40. for(int i = 1 ;i <= n ; ++i)
  41. scanf("%d" ,&T[i].x) ;
  42. for(int i = 1 ;i <= n ; ++i)
  43. scanf("%d" ,&T[i].y) ;
  44. sort(T+1 ,T+n+1 ,cmp) ;
  45. }
  46. void solve()
  47. {
  48. int ans = 0 ;
  49. memset(vis ,false ,sizeof(vis)) ;
  50. for(int i = 1 ;i <= n ; ++i)
  51. {
  52. int j = T[i].x ;
  53. for( ;j >= 1 ; --j)
  54. if(!vis[j])
  55. {
  56. vis[j] = true ;
  57. break ;
  58. }
  59. if(j == 0)
  60. ans += T[i].y ;
  61. }
  62. cout<<ans<<endl ;
  63. }
  64. int main()
  65. {
  66. int Tx ;
  67. scanf("%d" ,&Tx) ;
  68. while(Tx--)
  69. {
  70. input() ;
  71. solve() ;
  72. }
  73. return 0 ;
  74. }
















文章来源: blog.csdn.net,作者:Linux猿,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nyist_zxp/article/details/39296501

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。