NYOJ 1249 物資調度(DFS+剪枝)


題目鏈接:

http://acm.nyist.net/JudgeOnline/problem.php?pid=1249

描述

某地區發生了地震,災區已經非常困難,災民急需一些帳篷、衣物、食品和血漿等物資。可通往災區的道路到處都是塌方,70%以上的路面損壞,橋梁全部被毀。國家立即啟動應急預案,展開史上最大強度非作戰空運行動,准備向災區空投急需物資。

一方有難,八方支援。現在已知有N個地方分別有A1,A2,….,An個物資可供調配。目前災區需要物資數量為M。

現在,請你幫忙算一算,總共有多少種物質調度方案。

假設某地方一旦被選擇調配,則其物資數全部運走。

 
輸入
輸入一個組數T。(0<T<10)
之后為N,M含義分別如題目描述。(0<N<=100,0<M<=1000)
之后有N個數字A1,A2,….,An表示N個地方每個地方的物資數。(0<Ai<=1000)
輸出
對於每組測試數據,輸出一行:物資調度的總方案數
樣例輸入
2
4 4
1 1 2 2
4 6
1 1 2 2
樣例輸出
3
1
來源  第七屆河南省程序設計大賽
題意描述:
輸入物資的堆數及所需調動的物資數、每堆物資數
計算並輸出調度方案數
解題思路:
可以看成是有相同牌面的不同紙牌的排列,使用DFS的話,必定需要剪枝,因為全排列10張以上的牌速度就慢的可怕了(別說100張了),所以在搜索的時候向下傳遞i值,意即下次嘗試的時候直接從后面取就行了,這樣就避免了重復取牌。另外取的時候直接判斷會不會超出限度,是的話直接剪掉。詳見代碼。
AC代碼:
 1 #include<stdio.h>
 2 #include<string.h>
 3 void dfs(int step,int sum,int i);
 4 int ans,n,v,book[110],a[110];
 5 int main()
 6 {
 7     int T,i,z;
 8     scanf("%d",&T);
 9     while(T--)
10     {
11         scanf("%d%d",&n,&v);
12         z=0;//物資總和 
13         for(i=1;i<=n;i++)
14         {
15             scanf("%d",&a[i]);
16             z += a[i];
17         }
18         if(z <= v)
19         {
20             if(z<v)
21             printf("0\n");
22             else
23             printf("1\n");
24             continue;
25         }    
26         
27         ans=0;
28         memset(book,0,sizeof(book));
29         dfs(1,v,1);//向下傳遞放牌位置,所需物資數,取牌位置 
30         printf("%d\n",ans);
31     }
32     return 0;
33 }
34 void dfs(int step,int sum,int i)
35 {
36     int j;
37     if(step==n+1 || sum ==0) 
38     {
39         if(sum == 0)
40             ans++;
41         return;
42     }
43     for(;i<=n;i++)
44     {
45         if(sum < a[i])//必要剪枝 
46         continue;
47         if(!book[i])
48         {
49             book[i]=1;
50             sum -= a[i];
51             dfs(step+1,sum,i+1);
52             
53             book[i]=0;
54             sum += a[i];
55         }
56     }
57     return ;
58 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM