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