Line of Sight

看的题解。大概就是要相互看见,充要条件是在圆上的可视区域有公共点。于是就变成了一个求相交区间个数的题,排序。

没想出来大概是因为思考的时候一直局限于拿切线去扫,没有仔细考虑可视的性质。

Debug了一会,一个小bug是eps开太小了。

 1 //============================================================================
 2 // Name        : co13nov_sight.cpp
 3 // Author      : cad
 4 // Version     :
 5 // Copyright   : Your copyright notice
 6 // Description : Hello World in C++, Ansi-style
 7 //============================================================================
 8 #include <cstdio>
 9 #include <algorithm>
10 #include <iostream>
11 #include <cmath>
12 
13 using namespace std;
14 #define rep(i,n) for (int n__=n,i=1;i<=n__;i++)
15 #define repb(i,b,n) for (int n__=n,i=b;i<=n__;i++)
16 typedef double db;
17 
18 const db pi=acos(0)*2,eps=1e-10;
19 const int mN=50000+10;
20 struct ope
21 {
22     int fg;
23     db x;
24 } a[mN*4];
25 int ta=0;
26 bool operator<(const ope& a,const ope& b)
27 {
28     if (a.fg!=b.fg && fabs(a.x-b.x)<eps)
29     {
30         return a.fg<b.fg;
31     }
32     else
33         return a.x<b.x;
34 }
35 
36 void add(db l,db r)
37 {
38     a[++ta].fg=0;
39     a[ta].x=l;
40     a[++ta].fg=1;
41     a[ta].x=r;
42 }
43 int main()
44 {
45     freopen("sight.in","r",stdin);
46     freopen("sight.out","w",stdout);
47     int n;
48     db R;
49     cin>>n>>R;
50     int over=0;
51     rep(i,n)
52     {
53         db x,y;
54         cin>>x>>y;
55         db al=atan2(y,x);//to calc
56         if (al<0)
57             al+=2*pi;
58         db bt=acos(R/sqrt(x*x+y*y));//to calc
59         if (al+bt+eps>2*pi)
60         {
61             add(0,al+bt-2*pi);
62             add(al-bt,2*pi);
63             over++;
64         }
65         else if (al-bt<eps)
66         {
67             add(0,al+bt);
68             add(al-bt+2*pi,2*pi);
69             over++;
70         }
71         else
72         {
73             add(al-bt,al+bt);
74         }
75     }
76     sort(a+1,a+1+ta);
77     long long ans=0;
78     rep(i,ta)
79     {
80         static int now=0;
81         if (a[i].fg==0)
82         {
83             ans+=now;
84             now++;
85         }
86         else
87         {
88             now--;
89         }
90     }
91     ans-=(long long)over*(over-1)/2;
92     cout<<ans<<endl;
93 //    cout<<ta<<endl;
94     return 0;
95 }

 下面是别人家的写法,,,

  for(int iters = 0; iters < 2; iters++) {
    for(int i = 0; i < N; i++) { 
      /* Move the tangent forward to A[i].first and remove everything no longer
       * visible. */
      while(!q.empty() && q.top() < A[i].first) {
        q.pop();
      }

      if(iters == 1) {
        /* We iterate around the points twice but only count points added the
         * second iteration to ensure the sweep tangent contains what it
         * should. */
        result += q.size();
      }

      q.push(A[i].second);
      A[i].first += 2 * PI;
      A[i].second += 2 * PI;
    }
  }

 下一题

USACO 2013 November Contest, Gold
Problem 3. No Change

这题看懂题意就很水了,货物序列的顺序不变。。。

一个很简单的状态压缩就可以了。。。

 1 //============================================================================
 2 // Name        : co13nov_sight.cpp
 3 // Author      : cad
 4 // Version     :
 5 // Copyright   : Your copyright notice
 6 // Description : Hello World in C++, Ansi-style
 7 //============================================================================
 8 #include <cstdio>
 9 #include <algorithm>
10 #include <iostream>
11 #include <cstring>
12 #include <cmath>
13 
14 using namespace std;
15 #define rep(i,n) for (int n__=n,i=1;i<=n__;i++)
16 #define repb(i,b,n) for (int n__=n,i=b;i<=n__;i++)
17 typedef double db;
18 const int mC=17,mN=100000+10;
19 int c[mC],opti[mC];
20 int f[1<<mC];
21 int    s[mN],w[mN];
22 int bisc(int v,int l,int r)
23 {
24     int mid;
25     while (l<r)
26     {
27         mid=(l+r)/2;
28         if (s[mid+1]<=v)
29             l=mid+1;
30         else
31             r=mid;
32     }
33     return l;
34 }
35 int main()
36 {
37     freopen("nochange.in","r",stdin);
38     freopen("nochange.out","w",stdout);
39     int n,k;
40     cin>>k>>n;
41     rep(i,k)
42         cin>>c[i];
43     s[0]=0;
44     rep(i,n)
45     {
46         cin>>w[i];
47         s[i]=w[i]+s[i-1];
48     }
49 
50     memset(f,0,sizeof(f));
51     long long ans=-1;
52     repb(opt,1,(1<<(k))-1)
53     {
54         int bo=opt;
55         rep(i,k)
56         {
57             opti[i]=bo%2;
58             bo/=2;
59         }
60         rep(i,k)
61             if (opti[i])
62             {
63                 int bef=opt ^ (1<<(i-1));
64                 f[opt]=max(f[opt],bisc(s[f[bef]]+c[i],f[bef],n));
65             }
66         if (f[opt]==n)
67         {
68             long long tot=0;
69             rep(i,k)
70                 if (!opti[i])
71                 {
72                     tot+=c[i];
73                 }
74             ans=max(ans,tot);
75         }
76     }
77     cout<<ans<<endl;
78     return 0;
79 }

别人家的写法。

 1   vector<int> dp(1 << K);
 2     int ans = -1;
 3     for (int b = 1; b < (1 << K); b++)
 4     {
 5         int best = 0;
 6         int rem = 0;
 7         for (int i = 0; i < K; i++)
 8         {
 9             int m = 1 << i;//用位运算搞,不用开位数组了
10             if (b & m)
11             {
12                 int last = acc[dp[b ^ m]];
13                 int trg = upper_bound(acc.begin(), acc.end(), last + coins[i])
14                                          - acc.begin() - 1;//用stl,不用自己二分了
15                 if (trg > best)
16                     best = trg;
17             }
18             else//直接把统计和dp合并了
19                 rem += coins[i];
20         }