这是USACO4.1.2,题目大意是将几个给定木料尽可能多的切割成指定大小和个数的木块,由于没有指定顺序,很直观是搜索问题,木料N<=50,木块数R<=1023,单是搜索一次就有50^1023种可能,数字相当恐怖,必然要剪枝。
如果切割成K个指定木块能够成功,那么将这K个木块中最大的一个换成另外一个小一点的也必然能成功,那么显然要用贪心,先将木块升序排列,如果前K个可以切割成功,前K-1个也必然成功。那么此时二分优化也是很明显的了,最多搜索LOG(R)次即可。
但这些并没有改变单次搜索的复杂度,我在这里用了两个剪枝
1。如果切剩的废料总数比(木料总数-前K个木块总数)还大,停止搜索。但是其决定性意义的还是第二个剪枝,这个剪枝不要也可以AC
2。由于R<=1023,但是rail[i]<=128,显然这里有很多重复大小的木块,对相同大小的木块进行排列组合显然是没有意义的,所以我指定如果rail[i]==rail[i+1],那么rail[i]对应的board序号<=rail[i+1]对应的board序号,这样就减少了海量冗余情况。
贴一下代码(原谅我第一次写C++不会用STL)
1 /* 2 ID: ktboyyy1 3 PROG: fence8 4 LANG: C++ 5 */ 6 # include<iostream> 7 # include<cstdio> 8 using namespace std; 9 int board[100],board_t[100],rail[1500],tol_b[1500]; 10 int n,r,anss,tol,space,mid; 11 bool dfs(int pos,int local) 12 { 13 int i; 14 if (pos<1) 15 return true; 16 if (space>tol-tol_b[mid]) 17 return false; 18 for (i=local;i>=1;i--) 19 if (board_t[i]>=rail[pos]) 20 { 21 board_t[i]-=rail[pos]; 22 if (board_t[i]<rail[1]) 23 space+=board_t[i]; 24 if (rail[pos]==rail[pos-1]) 25 { 26 if (dfs(pos-1,i)) 27 return true; 28 } 29 else 30 { 31 if (dfs(pos-1,n)) 32 return true; 33 } 34 if (board_t[i]<rail[1]) 35 space-=board_t[i]; 36 board_t[i]+=rail[pos]; 37 } 38 return false; 39 } 40 void qsort(int s, int t,int a[]) 41 { 42 int i,j,x,temp; 43 i=s; j=t; x=a[(s+t)/2]; 44 do 45 { 46 while (a[i]<x) 47 i++; 48 while (a[j]>x) 49 j--; 50 if (i<=j) 51 { 52 temp=a[i]; 53 a[i]=a[j]; 54 a[j]=temp; 55 i++; 56 j--; 57 } 58 }while (i<=j); 59 if (i<t) qsort(i,t,a); 60 if (s<j) qsort(s,j,a); 61 } 62 int main(void) 63 { 64 int i,s,t,ans; 65 freopen("fence8.in","r",stdin); 66 freopen("fence8.out","w",stdout); 67 tol=0; 68 cin>>n; 69 for (i=1;i<=n;i++) 70 { 71 cin>>board[i]; 72 tol+=board[i]; 73 } 74 qsort(1,n,board); 75 tol_b[0]=0; 76 cin>>r; 77 for (i=1;i<=r;i++) 78 cin>>rail[i]; 79 qsort(1,r,rail); 80 for (i=1;i<=r;i++) 81 tol_b[i]=tol_b[i-1]+rail[i]; 82 s=1; t=r; mid=(s+t)/2; 83 ans=0; 84 while (s<=t) 85 { 86 space=0; 87 for (i=1;i<=n;i++) 88 board_t[i]=board[i]; 89 if (dfs(mid,n)) 90 { 91 s=mid+1; 92 ans=mid; 93 } 94 else 95 t=mid-1; 96 mid=(s+t)/2; 97 } 98 cout<<ans<<endl; 99 return 0; 100 }
浙公网安备 33010602011771号