lightoj 1018 - Brush (IV) 状压DP
2016-03-14 11:40
489 查看
有n个点,问可以用几条直线将所有点划去。
n是16,DP分类,很容易想到状压DP。dp[i]代表二进制状态下划去的点的集合下所需要的直线数量。
然后我们考虑的是加新的一条直线的情况下会划去那些点。枚举两个不在i状态的端点做直线,然后找在这条直线上的点...
然后TLE?
T是1000,时限2s,跑了2.8s,枚举直线上的点那个循环可以用预处理到数组中,1.6s..
n是16,DP分类,很容易想到状压DP。dp[i]代表二进制状态下划去的点的集合下所需要的直线数量。
然后我们考虑的是加新的一条直线的情况下会划去那些点。枚举两个不在i状态的端点做直线,然后找在这条直线上的点...
然后TLE?
T是1000,时限2s,跑了2.8s,枚举直线上的点那个循环可以用预处理到数组中,1.6s..
#include<bits/stdc++.h> using namespace std; int dp[1<<17]; vector<int> s[1<<17+3]; int line[17][17]; struct point { int x,y; } p[20]; int inti() { for(int i=0; i<=(1<<17)-1; i++) { for(int j=0; j<=16; j++) if((i&(1<<j))==0) s[i].push_back(j); } } int pd(int x,int y,int z)//判断三点是否共线 { return (p[x].x - p[y].x)*(p[x].y - p[z].y) == (p[x].y - p[y].y)*(p[x].x - p[z].x); } int main() { int t; inti(); scanf("%d",&t); for(int cas=1; cas<=t; cas++) { int n; scanf("%d",&n); memset(line,0,sizeof(line)); memset(dp,127,sizeof(dp)); for(int i=0; i<n; i++) { scanf("%d %d",&p[i].x,&p[i].y); line[i][i]=1<<i; } for(int i=0; i<n; i++) { for(int j=i+1; j<n; j++) { for(int k=0; k<n; k++) { if(pd(i,j,k)) line[i][j]|=(1<<k); } } } dp[0]=0; for(int i=0; i<(1<<n)-1; i++) { int x = s[i][0]; for (int j=0; j<s[i].size(); j++)//找出在i这个状态下没有选中的两个点当做直线两个点 { int y = s[i][j]; dp[i|line[x][y]] = min (dp[i|line[x][y]], dp[i]+1); } } printf("Case %d: %d\n",cas,dp[(1<<n)-1]); } return 0; }
相关文章推荐
- 开发经验小结--项目变动带来的开发开销
- PHP中GBK和UTF8乱码解决方案
- 什么是Shell? bash是干啥的? 有什么关系
- Xcode配置文件解析
- mac默认输入法其实挺好用
- 朴素贝叶斯分类器原理与java实现
- K2 BPM怎么让金融数据更有意义?
- LeetCode - 7. Reverse Integer
- 对Linux命令进一步学习vim(二)
- MVC阻止用户注入JavaScript代码或者Html标记
- 1110. Complete Binary Tree (25)
- is not a function
- FancyButtons一个漂亮的按钮库
- java线程基础知识
- php附近的人
- 通过java反射,封装bean
- ios中文字添加删除线
- Android 蓝牙开发实例--蓝牙聊天程序的设计和实现
- javascript实现数组去重的多种方法
- 红黑树