2018/2/2 dp还是不会做

先说一道卡了很久的题。

51Nod - 1006最长公共子序列Lcs

基础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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值