愤怒的小鸟P2831
2018-07-24 07:50:49来源:博客园 阅读 ()
题意:
有 n 个坐标,求用抛物线 y=ax^2+bx 将它们全部穿过所需的最少个数
思路:
状压dp 另外对于被同一条抛物线穿过的两点,有: a=(x2y1-x1y2)/(x1x2(x1-x2), b=(x1x1y2-x2x2y1)/(x1x2*(x1-x2))
code:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int n, m, t, p[200], dp[1<<18], cnt; void solve(double &a, double &b, double x1, double y1, double x2, double y2){ a = (x2 * y1 - x1 * y2) / (x1 * x2 * (x1 - x2)); b = (x1 * x1 * y2 - x2 * x2 * y1) / (x1 * x2 * (x1 - x2)); } bool inc(double a, double b, double x, double y){ double abs = a * x * x + b * x - y; if (abs < 0) abs = -abs; return abs <= 0.000001; } void pre(){ for (int i = 0; i <= (1<<18); i++) dp[i] = 0xffffff; cnt = 0; double x[20], y[20]; scanf("%d%d", &n, &m); for(int i = 0; i < n; i++) scanf("%lf%lf", &x[i], &y[i]); for(int i = 0; i < n; i++) { p[cnt++] = (1<<i); for(int j = i + 1, vis = 0; j < n; j++) if((vis>>j) & 1) continue; // 不能增加打掉的猪 else{ double a, b; solve(a, b, x[i], y[i], x[j], y[j]); if(a >= 0) continue; p[cnt] = (1<<i); for(int k = j; k < n; k++) if(inc(a, b, x[k], y[k])){ vis |= (1<<k); p[cnt] |= (1<<k); //01000101 表示能打1 3 7 这三只猪 } cnt++; } } } int ans(){ dp[0] = 0; for(int i = 0; i < (1<<n); i++) for(int j = 0; j < cnt; j++) dp[i | p[j]] = min(dp[i | p[j]], dp[i] + 1);//选取该条抛物线 或者加一条 return dp[(1<<n) - 1]; } int main(){ scanf("%d", &t); while(t--){ pre(); printf("%d\n", ans()); } return 0; }
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash