USACO 4.1 Fence rails(迭代加深DFS+二分)
没思路,实在是没想出如何爆搜。
查看题解,认真研究了nocow上的7个提示,然后发现我还是不会写,无奈之下,看别人代码,看了很多份,终于过了。。。
用到了迭代搜索(dfsid),就是说确定搜索的层数,将问题转化为n个木头能否切成k块木板,因为贪心策略,k块木板肯定是最小的k块,这样的搜索以前好像没这样写过,二分再加上两个优化就可以过了。加的是 浪费量和标记搜索木头,详细请看nocow上题解把。。。这份代码wood和board都是从小到大排的,把board从大到小排,同样也可以过,而且更快一点,但是wood必须从小到大。。。第二个优化必须根据wood从小到大。
1 /* 2 ID: cuizhe 3 LANG: C++ 4 TASK: fence8 5 */ 6 #include <iostream> 7 #include <cstdio> 8 #include <cstring> 9 #include <cmath> 10 #include <algorithm> 11 #include <map> 12 #include <string> 13 #include <vector> 14 using namespace std; 15 int board[55]; 16 int wood[1024],temp[1024]; 17 int wsum[1024]; 18 int n,r,z; 19 int maxz; 20 void dfs(int mid,int start) 21 { 22 int i,waste = 0,num = 1; 23 if(z) return ; 24 if(mid == 0) 25 { 26 z = 1; 27 return ; 28 } 29 for(i = 1;i <= n;i ++) 30 { 31 if(temp[i] < wood[1]) 32 waste += temp[i]; 33 } 34 if(waste > maxz) return ; 35 for(i = start;i <= n;i ++) 36 { 37 if(temp[i] >= wood[mid]) 38 { 39 if(mid-1 >= 1&&wood[mid] == wood[mid-1]) 40 num = i; 41 else 42 num = 1; 43 temp[i] -= wood[mid]; 44 dfs(mid-1,num); 45 temp[i] += wood[mid]; 46 } 47 } 48 return ; 49 } 50 int main() 51 { 52 int i,str,end,mid,sum = 0; 53 freopen("fence8.in","r",stdin); 54 freopen("fence8.out","w",stdout); 55 scanf("%d",&n); 56 for(i = 1; i <= n; i ++) 57 { 58 scanf("%d",&board[i]); 59 sum += board[i]; 60 } 61 sort(board+1,board+n+1); 62 for(i = 1;i <= n;i ++) 63 { 64 temp[i] = board[i]; 65 } 66 scanf("%d",&r); 67 for(i = 1; i <= r; i ++) 68 scanf("%d",&wood[i]); 69 sort(wood+1,wood+r+1); 70 for(i = 1; i <= r; i ++) 71 { 72 wsum[i] = wsum[i-1] + wood[i]; 73 } 74 str = 0; 75 end = r; 76 while(str < end) 77 { 78 mid = (str + end + 1)/2; 79 maxz = sum - wsum[mid]; 80 z = 0; 81 dfs(mid,1); 82 if(!z) 83 { 84 end = mid - 1; 85 } 86 else 87 { 88 str = mid; 89 } 90 } 91 printf("%d\n",str); 92 return 0; 93 }