zoukankan      html  css  js  c++  java
  • UVa 11008 Antimatter Ray Clearcutting(记忆化搜索)

    题意:

    n个坐标上面分别有n棵树,每发射一次枪,可以把一条直线上面的树都消灭掉。

    问要消灭到m棵树,最少需要几枪。

    思路:

    记忆化搜索。原则上每枪最少要消灭2棵树,如果最后一枪下去导致剩下的树小于等于(n-m),则控制最后一枪使结果恰好等于结果。其实发射枪的次数还是不变的。

    用一个整数的位表示剩下的树,预处理的过程中,g[i, j]表示与i树和j树在一条直线上面的树。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <climits>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 20;
    const int MAXD = 65600;
    int f[MAXD];
    int x[MAXN], y[MAXN];
    int g[MAXN][MAXN];
    int n, m, d;
    
    void init()
    {
        memset(g, 0, sizeof(g));
    
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < n; ++j)
                if (i != j)
                    for (int k = n - 1; k >= 0; --k)
                    {
                        g[i][j] <<= 1;
                        if((y[j] - y[i]) * (x[k] - x[i]) == (x[j] - x[i]) * (y[k] - y[i]))
                            ++g[i][j];
                    }
    }
    
    int dp(int u)
    {
        if (f[u] != -1)
            return f[u];
    
        int c = 0;
        for (int i = 0; i < n; ++i)
            if (u & (1<<i))
                ++c;
        if (c <= d)
            return f[u] = 0;
    
        if (c == 1)
            return f[u] = 1;
    
        int ans = INT_MAX;
        for (int i = 0; i < n; ++i)
            if (u & (1<<i))
                for (int j = i + 1; j < n; ++j)
                    if (u & (1<<j))
                        ans = min(ans, dp(u & (~g[i][j])) + 1);
    
        return f[u] = ans;
    }
    
    int main()
    {
        int cases, count = 0;
        scanf("%d", &cases);
        while (cases--)
        {
            scanf("%d %d", &n, &m);
            for (int i = 0; i < n; ++i)
                scanf("%d %d", &x[i], &y[i]);
    
            init();
    
            memset(f, -1, sizeof(f));
            d = n - m;
            int ans = dp((1<<n) - 1);
    
            printf("Case #%d:\n", ++count);
            printf("%d\n", ans);
            if (cases)
                printf("\n");
        }
        return 0;
    }

     

    -------------------------------------------------------

    kedebug

    Department of Computer Science and Engineering,

    Shanghai Jiao Tong University

    E-mail: kedebug0@gmail.com

    GitHub: http://github.com/kedebug

    -------------------------------------------------------

  • 相关阅读:
    win10安装.net3.5
    VS2015密钥
    wordpress目录文件结构说明
    js | javascript获取和设置元素的属性
    wordpress | WP Mail SMTP使用QQ邮箱发布失败的解决办法
    jquery 实时监听输入框值变化方法
    XPath编写规则学习
    如何将portfolio产品图片上的悬停去掉?
    wordpress怎么禁止文章复制
    js | javascript实现浏览器窗口大小被改变时触发事件的方法
  • 原文地址:https://www.cnblogs.com/kedebug/p/2787702.html
Copyright © 2011-2022 走看看