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 }