先说一道卡了很久的题。
基础dp。用回溯法把子序列求出来。然而这个oj有毒,明明输出一样死活WA,把cout改成printf后居然就过了。。。
dfs版:
#include <bits/stdc++.h>
#define show(a) cout << #a << " = " << a << endl;
#define MAXN 1005
using namespace std;
int dp[MAXN][MAXN] {};
string a,b;
int dfs(int x,int y)
{
int ans = 0;
if (x < 0 || y < 0)
return ans = 0;
if (dp[x][y] >= 0)
return dp[x][y];
else if (a[x] == b[y])
ans = dfs(x-1,y-1)+1;
else
ans = max(dfs(x,y-1),dfs(x-1,y));
return dp[x][y] = ans;
}
int main()
{
cin >> a >> b;
memset(dp,-1,sizeof dp);
int lena = a.length(),lenb = b.length();
int ans = dfs(lena-1,lenb-1);
int tmp = ans;
int i = lena - 1, j = lenb - 1;
char s[1005];
while (ans)
{
if (dp[i-1][j] == dp[i][j])
i--;
else if (dp[i][j-1] == dp[i][j])
j--;
else
{
s[ans] = b[j];
ans--;
i--; j--;
}
}
for (int i = 1; i <= tmp; i++)
printf("%c",s[i]);
cout << endl;
return 0;
}
递推版:
#include <bits/stdc++.h>
#define show(a) cout << #a << " = " << a << endl;
#define MAXN 1005
using namespace std;
int dp[MAXN][MAXN] {};
string a,b;
int main()
{
cin >> a >> b;
memset(dp,0,sizeof dp);
int lena = a.length(),lenb = b.length();
for (int i = 1; i <= lena; i++)
{
for (int j = 1; j <= lenb; j++)
{
if (a[i-1] == b[j-1])
dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
//printf("%3d",dp[i][j]);
}
//cout << endl;
}
int ans = dp[lena][lenb];
int tmp = ans;
int i = lena, j = lenb;
char s[1005];
while (ans)
{
//show(ans);
if (dp[i-1][j] == dp[i][j])
i--;
else if (dp[i][j-1] == dp[i][j])
j--;
else
{
s[ans] = b[j-1];
ans--;
i--; j--;
}
}
//show(i);show(j);show(tmp);
for (int i = 1; i <= tmp; i++)
printf("%c",s[i]);
cout << endl;
return 0;
}
C - 01背包
HihoCoder - 1038挑程例题。p51
dfs版:
#include <bits/stdc++.h>
#define show(a) cout << #a << " = " << a << endl;
const int MOD = 1e9+7;
const int MAXN = 10005;
using namespace std;
int dp[505][100005] {};
int n,money,need[200005],value[1005];
int dfs (int i, int j)
{
int ans = 0;
if (!i)
return 0;
if (dp[i][j] >= 0)
return dp[i][j];
if (j + need[i] <= money)
ans = max(dfs(i-1,j+need[i]) + value[i],dfs(i-1,j));
else
ans = dfs(i-1,j);
//show(ans);
return dp[i][j] = ans;
}
int main()
{
memset(dp,-1,sizeof dp);
cin >> n >> money;
for (int i = 1; i <= n; i++)
{
cin >> need[i] >> value[i];
}
cout << dfs(n,0);
return 0;
}
递推版:
#include <bits/stdc++.h>
#define show(a) cout << #a << " = " << a << endl;
const int MOD = 1e9+7;
const int MAXN = 10005;
using namespace std;
int dp[505][100005] {};
int n,money,need[200005],value[1005];
int main()
{
cin >> n >> money;
for (int i = 1; i <= n; i++)
{
cin >> need[i] >> value[i];
}
for (int i = 1; i <= n; i++)
{
for (int j = 0; j <= money; j++)
{
if (j + need[i] <= money)
{
dp[i][j] = max(dp[i-1][j],dp[i-1][j+need[i]]+value[i]);
}
else
dp[i][j] = dp[i-1][j];
//show(dp[i][j]);
}
}
cout << dp[n][0];
return 0;
}
数塔
HDU - 2084用一个数组来保存每一条路径,最后比较最大值。
#include <bits/stdc++.h>
#define show(a) cout << #a << " = " << a << endl;
const int MOD = 1e9+7;
const int MAXN = 105;
using namespace std;
int num[MAXN][MAXN],dp[MAXN][MAXN] {};
int main()
{
int t;
cin >> t;
while(t--)
{
int n,res = 0;
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= i; j++)
cin >> num[i][j];
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= i; j++)
{
dp[i][j] = max(dp[i-1][j],dp[i-1][j-1]) + num[i][j];
if (i == n)
res = max(res,dp[i][j]);
}
}
cout << res <<endl;
}
return 0;
}
一只小蜜蜂...
HDU - 2044递推。。注意边界条件
#include <bits/stdc++.h>
#define show(a) cout << #a << " = " << a << endl;
const int MOD = 1e9+7;
const int MAXN = 55;
using namespace std;
int main()
{
long long dp[MAXN][MAXN] {};
for (int i = 1; i <= 50; i++)
for (int j = i; j <= 50; j++)
{
dp[i][j] = 1;
}
for (int i = 1; i <= 50; i++)
for (int j = i+2; j <= 50; j++)
{
dp[i][j] = dp[i][j-1] + dp[i][j-2];
}
int n,a,b;
cin >> n;
while (n--)
{
cin >> a >> b;
cout << dp[a][b] << endl;
}
return 0;
}