uva 11008 Antimatter Ray Clearcutting

    技术2025-09-27  109

     

    Problem E Antimatter Ray Clearcutting Input: Standard Input

    Output: Standard Output

    It's year 2465, and you are the Chief Engineer for Glorified Lumberjacks Inc. on planet Trie. There is a number of trees that you need to cut down, and the only weapon you have is a high-powered antimatter ray that will cut through trees like butter. Fuel cells for the antimatter ray are very expensive, so your strategy is: stand somewhere in the forest and shoot the ray in some chosen direction. This will cut down all the trees that lie on the line in that direction. Given the locations of several trees and the number of trees that you are required to cut, what is the minimum number of shots that you need to fire?

    Input

    The first line of input gives the number of cases, N (at most 20). N test cases follow. Each one starts with 2 lines containing the integers n (the number of trees in the forest, at most 16) and m (the number of trees you need to cut, at most n). The next n lines will each give the (x,y) coordinates of a tree (integers in the range [-1000, 1000]).

    Output

    For each test case, output the line "Case #x:", where x is the number of the test case. On the next line, print the number of antimatter ray shots required to cut down at least m trees. Print an empty line between test cases.

     

    Sample Input                               Output for Sample Input

    2 4 4 0 0 0 1 1 0 1 1 9 7 0 0 1 1 0 2 2 0 2 2 3 0 3 1 3 2 3 4 Case #1: 2   Case #2: 2

     

    Notes

    In the first test case, you can cut down 4 trees by standing at (0, -1) and firing north (cutting 2 trees) and then standing at (1, -1) and again firing north (cutting 2 more trees).

    In the second test case, you should stand at (3,-1) and fire north (cutting 4 trees) and then stand at (-1, -1) and fire north-east (cutting 3 more trees).


    Problemsetter: Igor Naverniouk, EPS

    Special Thanks: Yury Kholondyrev

     

    #include <cstdio> #include <cstdlib> #include <cassert> #include <algorithm> #include <cmath> #include <vector> using namespace std; struct Point { int x; int y; }; vector <Point> point; vector <int> dp; vector <vector <int> > line; bool IsColinear(int a, int b, int c) { int x1 = point[a].x; int y1 = point[a].y; int x2 = point[b].x; int y2 = point[b].y; int x3 = point[c].x; int y3 = point[c].y; int diff = (x2 - x1) * (y3 - y2) - (x3 - x2) * (y2 - y1); return diff == 0; } void MakeLines() { line = vector <vector <int> > (point.size(), vector <int> (point.size(), 0)); for(int i=0; i<point.size(); ++i) { for(int k=0; k<point.size(); ++k) { for(int s=0; s<point.size(); ++s) { if(i == k || s == k || i == s) continue; if(IsColinear(i, k, s)) line[i][k] |= (1 << s); } line[i][k] |= (1 << i); line[i][k] |= (1 << k); } } } int Ones(int n) { static vector <int> cache(1 << 20, -1); assert(n < cache.size()); if(cache[n] != -1) return cache[n]; cache[n] = 0; int m = n; while(m != 0) { if((m & 1) != 0) ++cache[n]; m >>= 1; } #ifdef _DEBUG // printf("Ones(%x) = %d/n", n, cache[n]); #endif return cache[n]; } void DP() { dp.resize(1 << point.size()); dp[0] = 0; MakeLines(); for(int i=1; i<dp.size(); ++i) { dp[i] = Ones(i); for(int k=0; k<point.size(); ++k) { int maskK = 1 << k; if((i & maskK) == 0) continue; for(int s=k+1; s<point.size(); ++s) { int maskS = 1 << s; if((i & maskS) == 0) continue; dp[i] = min(dp[i], dp[i & (~line[k][s])] + 1); } } #ifdef _DEBUG printf("dp[%x] = %d/n", i, dp[i]); #endif } } void Solve() { static int cs = 1; int n; scanf("%d", &n); point.resize(n); int m; scanf("%d", &m); for(int i=0; i<n; ++i) scanf("%d%d", &point[i].x, &point[i].y); DP(); int ans = 0x3fffffff; for(int i=0; i<dp.size(); ++i) { if(m <= Ones(i) && Ones(i) <= n) ans = min(ans, dp[i]); } if(cs != 1) printf("/n"); printf("Case #%d:/n%d/n", cs++, ans); } int main() { int n; scanf("%d", &n); while(n-- > 0) Solve(); return 0; }  

     

    最新回复(0)