ACM ICPC 2017 Warmup Contest 2 I. Integral Polygons(计算几何+动态规划)

链接:https://nanti.jisuanke.com/t/17429

题意:给定一个由n个顶点组成的凸多边形,顶点都是整点,求有多少条对角线可以把该多边形分成两部分,满足两部分的面积都是整数。

分析:多边形面积S=1/2 |∑(xi*y(i+1)-x(i+1)*yi)|,只需要判断绝对值里的东西是否能被2整除。然后就是很奇怪的一个dp了。。设dp[t][k][a][b]为以第t个顶点为最后一个点,起点(x,y)=(a,b)mod2,对应的面积两倍mod2余k。然后O(n)处理dp[0],对xt-x(t+1)、yt-y(t+1)的奇偶性分情况dp,具体见代码。。最后把dp[i][0]求和,然后这个答案里考虑了以相邻点或者相同点为起点和终点的,所以要先-3*n,然后每种分法对应答案里的两种情况,所以答案要再除以2。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=2e5+5;
 6 typedef long long ll;
 7 int n;
 8 ll x[maxn],y[maxn],ans=0;
 9 ll dp[maxn][2][2][2];
10 //q[maxn],ans=0;
11 //ll dp1[maxn],dp2[maxn];
12 //ll sum[4][maxn];
13 //ll GetA(int s,int t){
14 //    if(s<=t)return sum[t-1]-sum[s-1]+x[t]*y[s]-x[s]*y[t];
15 //    return sum[t-1]+sum[n]-sum[s-1]+x[t]*y[s]-x[s]*y[t];
16 //}
17 ll GetArea(ll x1,ll y1,ll x2,ll y2,ll x3,ll y3){
18     return ((x2-x1)*(y2+y1)+(x3-x2)*(y3+y2)+(x1-x3)*(y1+y3));//((x2-x1)*(y2+y1)+(x3-x2)*(y3+y2)+(x1-x3)*(y1+y3))%2;
19 }
20 int main(){
21 //    freopen("e:\\in.txt","r",stdin);
22     while(scanf("%d",&n)!=EOF){
23         ans=0;
24         for(int i=0;i<n;i++){
25             scanf("%lld%lld",&x[i],&y[i]);
26             x[i]=(x[i]%2+2)%2;
27             y[i]=(y[i]%2+2)%2;
28         }
29         memset(dp,0,sizeof(dp));
30         ll sum=0;
31         for(int s=n-1;s>=0;s--){
32             sum+=GetArea(x[s],y[s],x[(s+1)%n],y[(s+1)%n],x[0],y[0]);
33             sum=(sum%2+2)%2;
34             dp[0][(sum%2+2)%2][x[s]%2][y[s]%2]++;
35         }
36         if(sum){
37             printf("0\n");continue;
38         }
39         for(int t=0;t<n-1;t++){
40             ll delta=x[t+1]*y[t]-x[t]*y[t+1];
41             delta=(delta%2+2)%2;
42             if(((x[t+1]-x[t])%2+2)%2==1&&((y[t+1]-y[t])%2+2)%2==1){
43                 for(int k=0;k<2;k++){
44                     dp[t+1][k][0][0]=dp[t][k^delta][0][0];
45                     dp[t+1][k][1][1]=dp[t][k^delta][1][1];
46                     dp[t+1][k][0][1]=dp[t][k^(delta^1)][0][1];
47                     dp[t+1][k][1][0]=dp[t][k^(delta^1)][1][0];
48                 }
49             }
50             else if(((x[t+1]-x[t])%2+2)%2==0&&((y[t+1]-y[t])%2+2)%2==1){
51                 for(int k=0;k<2;k++){
52                     dp[t+1][k][0][0]=dp[t][k^delta][0][0];
53                     dp[t+1][k][0][1]=dp[t][k^delta][0][1];
54                     dp[t+1][k][1][0]=dp[t][k^(delta^1)][1][0];
55                     dp[t+1][k][1][1]=dp[t][k^(delta^1)][1][1];
56                 }
57             }else if(((x[t+1]-x[t])%2+2)%2==1&&((y[t+1]-y[t])%2+2)%2==0){
58                 for(int k=0;k<2;k++){
59                     dp[t+1][k][0][0]=dp[t][k^delta][0][0];
60                     dp[t+1][k][1][0]=dp[t][k^delta][1][0];
61                     dp[t+1][k][0][1]=dp[t][k^(delta^1)][0][1];
62                     dp[t+1][k][1][1]=dp[t][k^(delta^1)][1][1];
63                 }
64             }else{
65                 for(int k=0;k<2;k++){
66                     dp[t+1][k][0][0]=dp[t][k^delta][0][0];
67                     dp[t+1][k][1][1]=dp[t][k^delta][1][1];
68                     dp[t+1][k][0][1]=dp[t][k^delta][0][1];
69                     dp[t+1][k][1][0]=dp[t][k^delta][1][0];
70                 }
71             }
72         }
73         for(int i=0;i<n;i++){
74             for(int X=0;X<2;X++){
75                 for(int Y=0;Y<2;Y++){
76                     ans+=dp[i][0][X][Y];
77                 }
78             }
79         }
80         ans-=3*n;
81         printf("%lld\n",ans/2);
82     }
83     return 0;
84 }

 

posted @ 2017-10-04 18:54  7391_KID  阅读(377)  评论(0编辑  收藏  举报