题意:你手中有一激光枪,能使你当前方向上的树全部砍倒。第一行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;
}