HDU 6365 Shoot Game区间dp+离散化

叁歲伎倆 2022-05-17 12:11 270阅读 0赞

传送门

这个题跟UVALive - 6938,的思路是一样的,感觉没做过那个题,这个题真的不好想。具体思路可以看

-》这个题

然后这个题就是将区间转化成了极角的区间,然后对极角区间离散化,同一个角度里的物体,取花费最高的那一个。还有就是这个题x,y, w值都比原来的题大,所以dp用long long ,极角排序的时候也要转化成long long

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const ll INF=0x3f3f3f3f3f3f3f3f;
  5. struct inter{
  6. int l, r, h;
  7. ll v;
  8. }ob[310];
  9. struct node{
  10. int x, y;
  11. }val[620];
  12. int mx, n, cnt;
  13. ll dp[1000][1000];
  14. bool cmp(node a, node b){
  15. return 1ll*a.x*b.y-1ll*a.y*b.x<=0;
  16. }
  17. inline void addval(int i){
  18. int tmp=__gcd(abs(ob[i].l), abs(ob[i].h));
  19. val[++mx]=(node){ob[i].l/tmp, ob[i].h/tmp};
  20. tmp=__gcd(abs(ob[i].r), abs(ob[i].h));
  21. val[++mx]=(node){ob[i].r/tmp, ob[i].h/tmp};
  22. }
  23. void lisan(){
  24. sort(val+1, val+1+mx, cmp);
  25. int x=1000000001, y=0;
  26. cnt=0;
  27. for(int i=1; i<=mx; i++){
  28. if(val[i].x!=x||val[i].y!=y){
  29. x=val[i].x, y=val[i].y;
  30. val[++cnt].x=x; val[cnt].y=y;
  31. }
  32. }
  33. for(int i=1; i<=n; i++){
  34. int x1, x2, y1, y2;
  35. int tmp=__gcd(abs(ob[i].l), abs(ob[i].h));
  36. x1=ob[i].l/tmp, y1=ob[i].h/tmp;
  37. tmp=__gcd(abs(ob[i].r), abs(ob[i].h));
  38. x2=ob[i].r/tmp; y2=ob[i].h/tmp;
  39. for(int j=1; j<=cnt; j++){
  40. if(val[j].x==x1&&val[j].y==y1)
  41. ob[i].l=j;
  42. if(val[j].x==x2 && val[j].y==y2)
  43. ob[i].r=j;
  44. }
  45. }
  46. }
  47. int main(){
  48. int T;
  49. scanf("%d", &T);
  50. while(T--){
  51. mx=0;
  52. scanf("%d", &n);
  53. for(int i=1; i<=n; i++){
  54. scanf("%d%d%d%lld", &ob[i].h, &ob[i].l, &ob[i].r, &ob[i].v);
  55. addval(i);
  56. }
  57. lisan();
  58. for(int d=2; d<=cnt+1; d++){
  59. for(int i=0; i+d<=cnt+1; i++){
  60. int j=i+d, id=-1;
  61. dp[i][j]=INF;
  62. for(int k=1; k<=n; k++){
  63. if(ob[k].l>i&&ob[k].r<j&&(id==-1||ob[id].v<ob[k].v))
  64. id=k;
  65. }
  66. if(id==-1){
  67. dp[i][j]=0;
  68. continue;
  69. }
  70. for(int k=ob[id].l; k<=ob[id].r; k++){
  71. dp[i][j]=min(dp[i][j], dp[i][k]+dp[k][j]+ob[id].v);
  72. }
  73. }
  74. }
  75. printf("%lld\n", dp[0][cnt+1]);
  76. }
  77. return 0;
  78. }
  79. /*
  80. 1
  81. 3
  82. 1 1 2 2
  83. 2 -1 1 4
  84. 3 -2 -1 3
  85. 3
  86. 1 -1 -1 10
  87. 2 -2 -2 1
  88. 1 1 1 100
  89. */

发表评论

表情:
评论列表 (有 0 条评论,270人围观)

还没有评论,来说两句吧...

相关阅读

    相关 UVALive - 6938 区间dp+离散

    [传送门][Link 1] 思路:一条射线最小的花费就是路径上最高的那个,对于时间这个区间,我们可以将其离散化成1~600的范围,因为有三百个点,最多就600个不同的数,转移