Aizu - 1379 Parallel Lines
题意:给出一些点,这些点两两相连成一条直线,问最多能连成多少条直线。
思路:暴力出奇迹!!记得当时比赛做这道题的时候一直依赖于板子,结果却限制了自己的思路,这得改。dfs直接暴力,但是需要将已经走过的点标记一下,用一个循环跳过已经标记的点减少dfs次数,不然得不出正确的结果,因为会出现如下的连线结果(左图),而正确的连线方式应该如右图。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <set> 5 #include <cstring> 6 #include <queue> 7 #define INF 0x3f3f3f3f 8 #define MIN(a,b) a<b ? a : b 9 #define MAX(a,b) a>b ? a : b//确实要比C++自带的max函数要快 10 #define FRE() freopen("in.txt","r",stdin) 11 using namespace std; 12 const int maxn = 20; 13 const int MOD = 1e9 + 7; 14 typedef long long ll; 15 typedef pair<int, int> P; 16 struct Point { 17 int x,y; 18 } p[maxn]; 19 struct Line { 20 int x,y; 21 } l[maxn]; 22 int m,ans,cnt,vis[maxn]; 23 24 int upDate() {//遍历任意两条边之间是否平行,更新最大的结果 25 int res = 0; 26 for(int i = 0; i<cnt; i++) 27 for(int j = i+1; j<cnt; j++) { 28 if(l[i].x*l[j].y == l[i].y*l[j].x){//注意有斜率不存在情况,所以要对等式做一下变形 29 res++; 30 } 31 } 32 return res; 33 } 34 35 void dfs(int now) { 36 while(vis[now])//减少dfs次数,同样也是避免出现之前说的情况 37 now++; 38 if(now == m) { 39 ans = MAX(upDate(),ans); 40 return; 41 } 42 vis[now] = 1; 43 for(int i = 0; i<m; i++) { 44 if(!vis[i] && cnt != i) { 45 l[cnt].x = p[now].x - p[i].x; 46 l[cnt].y = p[now].y - p[i].y; 47 vis[i] = 1; 48 cnt++; 49 dfs(now+1);//枚举的是每种连接方式下的点的个数 50 cnt--; 51 vis[i] = 0; 52 } 53 } 54 vis[now] = 0; 55 return; 56 } 57 58 59 int main() { 60 memset(vis,0,sizeof(vis)); 61 scanf("%d",&m); 62 for(int i = 0; i<m; i++) { 63 scanf("%d%d",&p[i].x,&p[i].y); 64 } 65 ans = 0; 66 cnt = 0; 67 dfs(0); 68 printf("%d\n",ans); 69 return 0; 70 }