uva 11008 Antimatter Ray Clearcutting

题意:你手中有一激光枪,能使你当前方向上的树全部砍倒。第一行t组测试数据。每一组测试数据,开始由两行构成,分别表示有n棵树,你要砍倒m棵树,接下来的n行给出的是n棵树的坐标(坐标范围是-1000到1000)。问你最少需要几枪才能达到。

我的做法是选两个点枚举所有的方向,跪了近三 秒,差点T,不过很可能T,如果RP不好的话。。。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=20;
struct node
{
    int x,y;
}line[N][N],poi[N];
int n,m,map[70000];
bool vis[70000];
inline int dp(int),calu(int),fun(int,int,int);
int main()
{
    int t,t_cnt=0;
    scanf("%d",&t);
    while(t--)
    {
        memset(vis,0,sizeof(vis));
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++) scanf("%d%d",&poi[i].x,&poi[i].y);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(i==j) continue;
                line[i][j].x=poi[i].x-poi[j].x;
                line[i][j].y=poi[i].y-poi[j].y;
            }
        }
        if(t_cnt!=0) puts("");
        printf("Case #%d:\n%d\n",++t_cnt,dp((1<<n)-1));
    }
    return 0;
}
int dp(int x)
{
    bool &flag=vis[x];
    int &res=map[x];
    int tree=calu(x);
    if(flag) return res;
    else if(tree<=n-m||tree==1)
    {
        flag=1;
        if(tree==1) res=1;
        else res=0;
        return res;
    }
    else
    {
        res=20;
        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                if(i==j||!(x&(1<<i)&&(x&(1<<j)))) continue;
                int temp=fun(x,i,j);
                res=min(res,dp(x^temp)+1);
            }
        }
        flag=1;
        return res;
    }
}
int fun(int sta,int x,int y)
{
    int temp=0;
    for(int i=0;i<n;i++)
    {
        if(sta&(1<<i)&&(line[i][y].x*line[x][y].y==line[x][y].x*line[i][y].y))
        {
            temp^=1<<i;
        }
    }
    return temp;
}
int calu(int x)
{
    int cnt=0;
    for(int i=0;i<n;i++)
    {
        if(x&(1<<i)) cnt++;
    }
    return cnt;
}


你可能感兴趣的:(struct,测试,tree,ini,fun)