有返回值int的代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a,b;
cin>>a>>b;
vector<vector<int>> map(a,vector<int>(b,0));
vector<vector<int>> f(a,vector<int>(5005,-1));
for(int i=0;i<a;i++){
for(int j=0;j<b;j++){
cin>>map[i][j];
}
}
int target;
cin>>target;
function<int(int,int)> dfs=[&](int row,int sum){
int res=INT_MAX;
if(row==a) return abs(sum-target);
else if(f[row][sum]!=-1) return f[row][sum];
else{
for(int i=0;i<b;i++){
res=min(dfs(row+1,sum+map[row][i]),res);
}
}
f[row][sum]=res;
return res;
};
cout<<dfs(0,0)<<endl;
return 0;
}
无返回值的代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a,b;
int ans=INT_MAX;
cin>>a>>b;
vector<vector<int>> map(a,vector<int>(b,0));
vector<vector<int>> f(a,vector<int>(5005,-1));
for(int i=0;i<a;i++){
for(int j=0;j<b;j++){
cin>>map[i][j];
}
}
int target;
cin>>target;
function<void(int,int)> dfs=[&](int row,int sum){
if(row==a-1){
for(int i=0;i<b;i++){
ans=min(ans,abs(target-(sum+map[row][i])));
}
}
else{
for(int i=0;i<b;i++){
dfs(row+1,sum+map[row][i]);
}
}
};
dfs(0,0);
cout<<ans<<endl;
return 0;
}
上面两份代码第一份是可以通过的(因为多了记忆化搜索),第二份超时了。在这题中,由于我们想加入记忆化搜索,如果没有返回值,会导致运行和记录的不同步(确切值的记录),所以选择有返回值的会容易写一点。
另附上一种dp写法:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<vector<int>> map(n, vector<int>(m));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> map[i][j];
}
}
int target;
cin >> target;
// 最大可能的和
int max_sum = n * 50;
vector<bool> dp(max_sum + 1, false);
dp[0] = true;
for (int i = 0; i < n; i++) {
vector<bool> new_dp(max_sum + 1, false);
for (int j = 0; j <= max_sum; j++) {
if (dp[j]) {
for (int k = 0; k < m; k++) {
if (j + map[i][k] <= max_sum) {
new_dp[j + map[i][k]] = true;
}
}
}
}
dp = new_dp;
}
int ans = INT_MAX;
for (int i = 0; i <= max_sum; i++) {
if (dp[i]) {
ans = min(ans, abs(target - i));
}
}
cout << ans << endl;
return 0;
}