标签:
题目链接:http://poj.org/problem?id=3684
把球的碰撞看作直接穿过
因为自始至终球的相对位置顺序都没有改变 所以最后sort一下即可得到各个球的位置
球有半径
这里的处理是
先把球看作质点
最后从下往上输出的时候再把(i-1)*2*R加上即可
注意半径给的单位是厘米
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <set> #include <stack> #include <queue> #include <vector> #include <cmath> #include <map> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> P; typedef struct { int x, y; }Node; const int maxn = 210; const int walk[][2] = {1, 0, 0, 1, -1, 0, 0, -1}; int n, m; char a[maxn][maxn]; Node v[20]; bool judge(int s, int sum, int turnid) { int vid = 0; set<P> check; for(int i = 0; i < sum; i++) //确定非转向灯是否能合法放置 并记录他们所能照亮的房间 { if(s & (1 << i) && i != turnid) { if(v[i].x - 1 >= 1 && v[i].x - 1 <= n && a[v[i].x - 1][v[i].y] != ‘.‘) return 0; if(v[i].y + 1 >= 1 && v[i].y + 1 <= m && a[v[i].x][v[i].y + 1] != ‘.‘) return 0; check.insert(P(v[i].x, v[i].y)); if(v[i].x - 1 >= 1) check.insert(P(v[i].x - 1, v[i].y)); if(v[i].y + 1 <= m) check.insert(P(v[i].x, v[i].y + 1)); } } for(int i = 0; i < 4; i++) //枚举转向灯的四个方向 { int cnt = check.size(); int x1 = v[turnid].x; int y1 = v[turnid].y; int x2 = x1 + walk[i][0]; int y2 = y1 + walk[i][1]; int x3 = x1 + walk[(i+1)%4][0]; int y3 = y1 + walk[(i+1)%4][1]; if(x2 >= 1 && x2 <= n && y2 >= 1 && y2 <= m && a[x2][y2] != ‘.‘) continue; if(x3 >= 1 && x3 <= n && y3 >= 1 && y3 <= m && a[x3][y3] != ‘.‘) continue; if(!check.count(P(x1, y1))) cnt++; if(x2 >= 1 && x2 <= n && y2 >= 1 && y2 <= m && !check.count(P(x2, y2))) cnt++; if(x3 >= 1 && x3 <= n && y3 >= 1 && y3 <= m && !check.count(P(x3, y3))) cnt++; if(cnt == sum) //已照亮的房间 == 需要被照亮的房间 return 1; } return 0; } int main() { //freopen("in.txt", "r", stdin); while(scanf("%d%d", &n, &m) == 2 && !(n == 0 && m == 0)) { for(int i = 1; i <= n; i++) scanf("%s", a[i]+1); int cnt = 0; //记录总共有几个格子可以放灯 for(int i = 1; i <= n; i++) //先把小于等于15个格子提出来 for(int j = 1; j <= m; j++) { if(a[i][j] == ‘.‘) { v[cnt].x = i; v[cnt].y = j; cnt++; } } if(cnt == 0) //特判 { printf("0\n"); continue; } int ans = 20; for(int i = 1; i < (1 << cnt); i++) { int lcnt = 0; //记录有几个灯 int ltmp[20]; //记录灯对应的v[]的下标 for(int j = 0; j < cnt; j++) if(i & (1 << j)) ltmp[lcnt++] = j; for(int j = 0; j < lcnt; j++) if(judge(i, cnt, ltmp[j]) && lcnt < ans) ans = lcnt; } if(ans == 20) printf("-1\n"); else printf("%d\n", ans); } return 0; }
poj 3684 Physics Experiment 弹性碰撞
标签:
原文地址:http://www.cnblogs.com/dishu/p/4314109.html