思路:
两种方法可做。
第一种meet in the middle暴力可过。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1.0);
int n, m, k;
vector< priority_queue<string, vector<string>, greater<string> > > mp;
string ans;
vii mat;
void recur(int r, int c, int limit, string &str, int val){
if(c < 0 || c >= (int)mat[r].size())
return;
if(r == limit - 1){
mp[val + mat[r][c]].push(str);
return;
}
if(!r){
str.push_back(c + '0');
str.push_back(' ');
}
for(int i = -1; i < 1; i++){
if(i == -1)
str.push_back('L');
else
str.push_back('R');
recur(r + 1, c + i, limit, str, val + mat[r][c]);
str.pop_back();
}
}
ll found(int r, int c, int limit, string &str, int val){
if(c < 0 || c >= (int)mat[r].size())
return 0;
if(r == limit - 1){
if(m - val - mat[r][c] >= 0 && !mp[m - val - mat[r][c]].empty()){
string cur = mp[m - val - mat[r][c]].top() + str;
if(ans.empty() || cur < ans)
ans = cur;
return (ll)mp[m - val - mat[r][c]].size();
}
else
return 0;
}
ll res = 0;
for(int i = 0; i <= 1; i++){
if(i == 0)
str.push_back('L');
else
str.push_back('R');
res += found(r + 1, c + i, limit, str, val + mat[r][c]);
str.pop_back();
}
return res;
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
while(cin >> n >> m, n + m){
ans.clear();
mp.clear();
mp.resize(100 * n);
mat.clear();
mat.resize(2 * n - 1);
for(int i = 0; i < n; i++){
mat[i].resize(n - i);
for(int j = 0; j < n - i; j++)
cin >> mat[i][j];
}
for(int i = 1; i < n; i++){
mat[i + n - 1].resize(i + 1);
for(int j = 0; j <= i; j++)
cin >> mat[i + n - 1][j];
}
string str;
for(int i = 0; i < n; i++){
recur(0, i, n, str, 0);
str.clear();
}
ll res = found(n - 1, 0, 2 * n - 1, str, 0 - mat[n - 1][0]);
cout << res << endl;
for(int i = 0; i < (int)ans.length(); i++){
if(!i)
cout << (int)(ans[i] - '0');
else
cout << ans[i];
}
cout << endl;
}
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
第二种dp[i][j][c]表示在i行j列有多少种方法能构成c。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1.0);
int n, m, k;
vii mat;
vector<vector<vll> > dp;
vector<vector<vector<string> > > str;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
while(cin >> n >> m, n + m){
mat.clear();
mat.resize(2 * n - 1);
for(int i = 0; i < n; i++){
mat[i].resize(n - i);
for(int j = 0; j < (int)mat[i].size(); j++)
cin >> mat[i][j];
}
for(int i = 2; i <= n; i++){
mat[n + i - 2].resize(i);
for(int j = 0; j < (int)mat[n + i - 2].size(); j++)
cin >> mat[n + i - 2][j];
}
dp.clear();
dp.resize(mat.size());
str.clear();
str.resize(mat.size());
for(int i = 0; i < n; i++){
dp[i].resize(mat[i].size(), vll(m + 1));
str[i].resize(mat[i].size(), vector<string>(m + 1));
if(!i){
for(int j = 0; j < (int)dp[i].size(); j++){
dp[i][j][mat[i][j]] = 1;
str[i][j][mat[i][j]].push_back(j + '0');
str[i][j][mat[i][j]].push_back(' ');
// cerr << i << " " << j << " " << mat[i][j] << " " << str[i][j][mat[i][j]] << endl;
}
}
else{
for(int j = 0; j < (int)dp[i].size(); j++){
for(int t = 0; t < 2; t++){
if(j + t < 0 || j + t >= (int)dp[i - 1].size())
continue;
for(int c = 0; c + mat[i][j] <= m; c++){
if(!dp[i - 1][j + t][c])
continue;
dp[i][j][c + mat[i][j]] += dp[i - 1][j + t][c];
string cur = str[i - 1][j + t][c];
cur.push_back(t ? 'L' : 'R');
if(str[i][j][c + mat[i][j]].empty())
str[i][j][c + mat[i][j]] = cur;
else
str[i][j][c + mat[i][j]] = min(str[i][j][c + mat[i][j]], cur);
// cerr << i << " " << j << " " << c + mat[i][j] << " " << str[i][j][c + mat[i][j]] << endl;
}
}
}
}
}
for(int i = n; i < 2 * n - 1; i++){
dp[i].resize(mat[i].size(), vll(m + 1));
str[i].resize(mat[i].size(), vector<string>(m + 1));
for(int j = 0; j < (int)dp[i].size(); j++){
for(int t = -1; t < 1; t++){
if(j + t < 0 || j + t >= (int)dp[i - 1].size())
continue;
for(int c = 0; c + mat[i][j] <= m; c++){
if(!dp[i - 1][j + t][c])
continue;
dp[i][j][c + mat[i][j]] += dp[i - 1][j + t][c];
string cur = str[i - 1][j + t][c];
cur.push_back(t ? 'R' : 'L');
if(str[i][j][c + mat[i][j]].empty())
str[i][j][c + mat[i][j]] = cur;
else
str[i][j][c + mat[i][j]] = min(str[i][j][c + mat[i][j]], cur);
// cerr << i << " " << j << " " << c + mat[i][j] << " " << str[i][j][c + mat[i][j]] << endl;
}
}
}
}
ll res = 0;
for(int i = 0; i < (int)dp[2 * n - 2].size(); i++)
res += dp[2 * n - 2][i][m];
cout << res << endl;
string ans;
for(int i = 0; i < (int)dp[2 * n - 2].size(); i++){
if(ans.empty())
ans = str[2 * n - 2][i][m];
else if(!str[2 * n - 2][i][m].empty())
ans = min(ans, str[2 * n - 2][i][m]);
}
for(int i = 0; i < (int)ans.length(); i++){
if(!i)
cout << ans[i] - '0';
else
cout << ans[i];
}
cout << endl;
}
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
未来可期。