【问题描述】
m× m的方阵上有n棵葱,你要修一些栅栏把它们围起来。一个栅栏是一段
沿着网格建造的封闭图形(即要围成一圈) 。各个栅栏之间应该不相交、不重叠
且互相不包含。如果你最多修k个栅栏,那么所有栅栏的长度之和最小是多少?
【输入格式】
第一行三个整数m,k,n。
接下来n行每行两个整数x,y代表某棵葱的位置。
【输出格式】
一行一个整数代表答案。
【样例输入 1】
6 1 4
1 3
4 2
4 4
6 4
【样例输出 1】
18
【样例输入 2】
6 2 4
1 3
4 2
4 4
6 4
【样例输出 2】
16
【样例解释】
你猜树上有啥。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int N=1e6+10; 5 const int M=20; 6 int m,n,k,xx[M],yy[M]; 7 int cost[N],s[M]; 8 int tot,nowmask,answer,full; 9 struct rect{ 10 int x1,x2,y1,y2; 11 int mask,w; 12 rect(){} 13 rect(int _x1,int _y1,int _x2,int _y2){ 14 x1=_x1,y1=_y1,x2=_x2,y2=_y2; 15 mask=0; 16 for(int i=0;i<n;i++) if(x1<=xx[i]&&xx[i]<=x2&&y1<=yy[i]&&yy[i]<=y2) mask|=(1<<i); 17 w=((x2-x1+1)+(y2-y1+1))*2; 18 if(mask==full) answer=w; 19 } 20 }a[N]; 21 void dfs(int cnt,int j,int cost){ 22 if(nowmask==full){ 23 //if(clock()>=1950){printf("%d",answer);exit(0);} 24 answer=min(answer,cost);return ; 25 } 26 if(cnt>=k||j>tot||cost>=answer) return ; 27 for(int i=j;i<=tot;i++){ 28 if(nowmask&a[i].mask) continue; 29 nowmask^=a[i].mask; 30 dfs(cnt+1,i+1,cost+a[i].w); 31 nowmask^=a[i].mask; 32 } 33 } 34 void DFS(int now,int cnt,int res){ 35 if(now==n){ 36 if(res<answer) answer=res;return; 37 } 38 if(res+(k-cnt)*4>=answer) return; 39 for(int i=1;i<=cnt;i++){ 40 int pres=s[i]; 41 s[i]|=(1<<now); 42 DFS(now+1,cnt,res-cost[pres]+cost[s[i]]); 43 s[i]^=(1<<now); 44 } 45 if(cnt<k){ 46 s[++cnt]=(1<<now); 47 DFS(now+1,cnt,res+4); 48 } 49 } 50 #define name "dan" 51 int main(){ 52 scanf("%d%d%d",&m,&k,&n); 53 full=(1<<n)-1; 54 for(int i=0;i<n;i++) scanf("%d%d",&xx[i],&yy[i]); 55 if(n<15){ 56 for(int i=0;i<n;i++){ 57 for(int j=i;j<n;j++){ 58 for(int k=j;k<n;k++){ 59 for(int l=k;l<n;l++){ 60 a[++tot]=rect(min(min(xx[i],xx[j]),min(xx[k],xx[l])),min(min(yy[i],yy[j]),min(yy[k],yy[l])), 61 max(max(xx[i],xx[j]),max(xx[k],xx[l])),max(max(yy[i],yy[j]),max(yy[k],yy[l]))); 62 } 63 } 64 } 65 } 66 nowmask=0; 67 dfs(0,1,0); 68 printf("%d",answer); 69 } 70 else{ 71 answer=4000; 72 for(int i=1;i<=full;i++){ 73 int sx=1001,mx=-1,sy=1001,my=-1; 74 for(int j=0;j<n;j++){ 75 if((i>>j)&1){ 76 if(xx[j]<sx) sx=xx[j]; 77 if(xx[j]>mx) mx=xx[j]; 78 if(yy[j]<sy) sy=yy[j]; 79 if(yy[j]>my) my=yy[j]; 80 } 81 } 82 cost[i]=(mx-sx+1)*2+(my-sy+1)*2; 83 } 84 DFS(0,0,0); 85 printf("%d",answer); 86 } 87 return 0; 88 }
版权申明:转载于shenben
思路:搜索,好好理解
时间: 2024-10-30 16:18:56