UVA 11008 Antimatter Ray Clearcutting

举报
Linux猿 发表于 2021/08/04 23:17:12 2021/08/04
【摘要】 题目链接~~> 做题感悟:这题最开始的想法是先处理一下在同一条直线上的点用二进制压缩一下,然后用背包处理一下,但是超时了 ,后来看了别人写的才知道原来这样也可以,但是我在去除一条线段上的点的时候用抑或做的,这样是不行的,如果是单独一个点的话就可以。 解题思路:记忆化 + 状态压缩             ...

题目链接~~>

做题感悟:这题最开始的想法是先处理一下在同一条直线上的点用二进制压缩一下,然后用背包处理一下,但是超时了 ,后来看了别人写的才知道原来这样也可以,但是我在去除一条线段上的点的时候用抑或做的,这样是不行的,如果是单独一个点的话就可以。

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

              这题第一感觉是要把同一条直线上的点用二进制压缩一下,那么,同一条直线上的点怎样压缩呢 ? 可以用key[ i ] [  j ] 记录在直线 i  , j 上有多少点存在,这样如果想打掉这条直线的话,就一同打掉在直线上所有的点,判断是否在 i , j 直线上时比较一下斜率就可以了,这里要用乘法判断斜率相等,这样就避免了斜率是正无穷的那种情况,这样第一步就算完成了。

            接下来就是记忆化搜索了,这里用记忆化搜索比较方便也比较好想,开始当然是一棵树也没有砍掉,传递 (1<<n)-1 ,那么,dp[ S ] 代表到达 S 状态是最少要砍几次,其中 S中二进制位上0 的个数代表已经砍掉几棵树,从而如果 S 中 0 (即 1 的个数不大于 n-m) 的个数大于等于 m 时,就不需要继续砍树了,还有一种特殊情况:如果只有一棵树那么久只需要一次就可以了,so~>返回 1 .

代码:


  
  1. #include<iostream>
  2. #include<fstream>
  3. #include<iomanip>
  4. #include<ctime>
  5. #include<fstream>
  6. #include<sstream>
  7. #include<stack>
  8. #include<cstring>
  9. #include<map>
  10. #include<vector>
  11. #include<cstdio>
  12. #include<algorithm>
  13. #define INT long long int
  14. using namespace std ;
  15. const double esp = 0.00000001 ;
  16. const int INF = 1000000000 ;
  17. const int MY = 20 ;
  18. const int MX = (1<<17) + 10 ;
  19. int n ,m ;
  20. int dp[MX] ,key[MY][MY] ,a[MY] ,b[MY] ;
  21. int DP_Memory(int S)
  22. {
  23. if(dp[S] != -1) return dp[S] ;
  24. int cnt = 0 ;
  25. int& ans = dp[S] ;
  26. for(int i = 0 ;i < n ;i++)
  27. if(S &(1<<i))
  28. cnt++ ;
  29. if(cnt <= n-m) return ans = 0 ;
  30. if(cnt == 1) return ans = 1 ;
  31. ans = INF ;
  32. for(int i = 0 ;i < n ;i++)
  33. for(int j =i+1 ;j < n ;j++)
  34. if((S &(1<<i)) && (S &(1<<j)))
  35. ans = min(ans ,DP_Memory(S &(~key[i][j]))+1) ;// 切记不要用抑或处理!!
  36. return ans ;
  37. }
  38. void init()// 处理两点构成的直线上有包含点
  39. {
  40. memset(key ,0 ,sizeof(key)) ;
  41. memset(dp ,-1 ,sizeof(dp)) ;
  42. for(int i = 0 ;i < n ;i++)
  43. for(int j = i+1 ;j < n ;j++)
  44. for(int k = 0 ;k < n ;k++)
  45. if((b[j]-b[i])*(a[k]-a[i]) == (b[k]-b[i])*(a[j]-a[i]))
  46. key[i][j] |=(1<<k) ;
  47. }
  48. int main()
  49. {
  50. int Tx ,cse=1 ;
  51. scanf("%d",&Tx) ;
  52. while(Tx--)
  53. {
  54. scanf("%d%d",&n ,&m) ;
  55. for(int i = 0 ;i < n ;i++)
  56. scanf("%d%d",&a[i] ,&b[i]) ;
  57. init() ;
  58. cout<<"Case #"<<cse++<<":"<<endl ;
  59. cout<<DP_Memory((1<<n)-1)<<endl ;
  60. if(Tx) cout<<endl ;
  61. }
  62. return 0 ;
  63. }


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

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

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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