1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 int n, C; 5 int nc, nw; 6 int ans; 7 int cost[60][3], weight[60][3]; 8 void dfs(int i) { 9 if (i == n) ans= min(ans, nw); 10 for (int j = 0; j < 3; j++) { 11 nc += cost[i][j]; 12 nw += weight[i][j]; 13 if (nc < C&&nw<ans) 14 dfs(i + 1); 15 nc -= cost[i][j]; 16 nw -= weight[i][j]; 17 } 18 } 19 int main() { 20 while (cin >> n >> C) { 21 for (int i = 0; i < n; i++) { 22 for (int j = 0; j < 3; j++) { 23 cin >> weight[i][j] >> cost[i][j]; 24 } 25 } 26 ans = 0x3f3f3f3f; 27 dfs(0); 28 cout << ans<<endl; 29 } 30 return 0; 31 }
题意:输入两个数n,C表示以下n行,之后每行6个数,两个数一组,第一个数表示该部件质量,第二个数表示该部件的花费。要求在总cost<C的条件下,从每行选一个部件,使得总质量最小。
思路:函数dfs[i]表示选第i个部件的过程,该过程中有三个部件要选择,因此需建立一个三次的循环,每次循环表示尝试选各种部件。
先看递归结束的条件,显然,当次数i==n时,表示已经选完最后一个部件。在进入函数前将结果ans设为无穷大INF,若每次递归结束时得到的质量nw<ans,则更新ans的值。故只有在每次达到递归结束条件时才会更新ans!!
再看循环中,每次循环即是假设已经选了该部件,故先将总质量,总花费更新一次。只有当花费未超标,且当前质量小于已知ans时(毕竟若还未选完就已经大于ans,则无继续必要),再进入下一层递归,即在选该部件的情况下继续挑选其它部件。之后还应还原会原先状态,表示未选该部件,以便继续尝试其它部件。
由于dfs尝试了每一种挑选可能,故复杂度为O(3^n)。
代码:
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 int n, C; 5 int nc, nw; 6 int ans; 7 int cost[60][3], weight[60][3]; 8 void dfs(int i) { 9 if (i == n) ans= min(ans, nw); 10 for (int j = 0; j < 3; j++) { 11 nc += cost[i][j]; 12 nw += weight[i][j]; 13 if (nc < C&&nw<ans) 14 dfs(i + 1); 15 nc -= cost[i][j]; 16 nw -= weight[i][j]; 17 } 18 } 19 int main() { 20 while (cin >> n >> C) { 21 for (int i = 0; i < n; i++) { 22 for (int j = 0; j < 3; j++) { 23 cin >> weight[i][j] >> cost[i][j]; 24 } 25 } 26 ans = 0x3f3f3f3f; 27 dfs(0); 28 cout << ans<<endl; 29 } 30 return 0; 31 }