hdu 4739 Zhuge Liang's Mines 2013 ACM/ICPC Asia Regional Hangzhou Online
比赛的时候跟学长说了一下我的想法,贪心,首先排序,x从小到大排序,x相同的y从小到大,然后优先选择边长小的能组成正方形的点。
但是写跪了,后来交给学长写状态压缩dp。今天看到结题报告里有人用的类似的方法过了,查看后发现是我没有判断重点的情况,改后怒ac,
还是太弱了,不然可以省下点时间做其他的题目。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #define maxlen 30 6 using namespace std; 7 int maps[110][110]; 8 struct node 9 { 10 int x,y; 11 }p[maxlen]; 12 int n; 13 bool cmp(node a,node b) 14 { 15 if(a.x==b.x) 16 return a.y<b.y; 17 else 18 return a.x<b.x; 19 } 20 bool judge(int x,int y) 21 { 22 return x>=0&&x<=100&&y>=0&&y<=100; 23 } 24 int main () 25 { 26 while(scanf("%d",&n)!=EOF) 27 { 28 if(n==-1) 29 break; 30 memset(maps,0,sizeof(maps)); 31 for(int i=0;i<n;++i) 32 { 33 scanf("%d%d",&p[i].x,&p[i].y); 34 maps[p[i].x][p[i].y]++; 35 } 36 sort(p,p+n,cmp); 37 int ans=0; 38 for(int i=0;i<n;++i) 39 { 40 for(int j=-100;j<=100;++j) 41 { 42 if(j!=0&&judge(p[i].x+j,p[i].y+j)&&judge(p[i].x,p[i].y+j)&&judge(p[i].x+j,p[i].y)) 43 if(maps[p[i].x+j][p[i].y+j]&&maps[p[i].x][p[i].y+j]&&maps[p[i].x+j][p[i].y]&&maps[p[i].x][p[i].y]) 44 { 45 maps[p[i].x+j][p[i].y+j]--;maps[p[i].x][p[i].y+j]--;maps[p[i].x+j][p[i].y]--;maps[p[i].x][p[i].y]--; 46 ans+=4; 47 } 48 } 49 } 50 printf("%d\n",ans); 51 } 52 }
正解是状态压缩,其实也是十分简单,一共就20个点,转化为二进制后即可以用一个整数表示整个状态。
dp[s]表示s这个状态下最多的正方形数。状态的转移也很简单。
dp[s]=max(dp[s],dp[s']+1)
如果可以组成正方形即可转到另一个状态。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define maxlen 1<<21 6 using namespace std; 7 int n; 8 int dp[maxlen]; 9 int used[30]; 10 struct node 11 { 12 int x,y; 13 }p[30]; 14 bool cmp(node a,node b) 15 { 16 return a.x==b.x?a.y<b.y:a.x<b.x; 17 } 18 bool judge(node a,node b,node c,node d) 19 { 20 return (a.x==b.x&&a.y==c.y&&c.x==d.x&&b.y==d.y&&b.y-a.y==c.x-a.x); 21 } 22 int dfs(int s) 23 { 24 if(s<0) 25 return 0; 26 if(dp[s]) 27 return dp[s]; 28 for(int i=0;i<n;++i) 29 { 30 for(int j=i+1;j<n;++j) 31 { 32 for(int k=j+1;k<n;++k) 33 { 34 for(int l=k+1;l<n;++l) 35 { 36 if(judge(p[i],p[j],p[k],p[l])&&!used[i]&&!used[j]&&!used[k]&&!used[l]) 37 { 38 used[i]=used[j]=used[k]=used[l]=true; 39 int x = s-(1<<i)-(i<<j)-(1<<k)-(1<<l); 40 dp[s] = max(dp[s],1+dfs(x)); 41 used[i]=used[j]=used[k]=used[l]=false; 42 } 43 } 44 } 45 } 46 } 47 return dp[s]; 48 } 49 int main () 50 { 51 while(scanf("%d",&n)!=EOF) 52 { 53 if(n==-1) 54 break; 55 for(int i=0;i<n;++i) 56 scanf("%d%d",&p[i].x,&p[i].y); 57 sort(p,p+n,cmp); 58 memset(dp,0,sizeof(dp)); 59 memset(used,0,sizeof(used)); 60 int ans = dfs((1<<n)-1); 61 printf("%d\n",4*ans); 62 } 63 }