dp46道~学习

10 篇文章 0 订阅

本来打算寒假的最后几天争取看能不能把dp46道给搞定的,结果发现过年的时候不想刷题,过完年之后大家又忙着去学校吃离别的饭了,于是嘛,计划又只是一个幌子

题目:来自 hdu 

分类(我是看这儿的):动态规划(46道题目)

目测开学之前是刷不完了,如果只是为了完成计划盲目的去做题,还不如不做,因为感觉那样的话,解决一个问题的本质就早已变了,如果是为了变强的话,在思维上进步就行了,做了多少多少题只能证明你编程有一段时间了,并不能证明你有多牛逼,或者说你的水平有多高,所以呢,不想做题的时候,简单地总结总结就好,快开学了,想联系的同学一起出去玩玩,出去闹闹,以后见面的日子就短了,没玩过的游戏也可以尝试尝试,毕竟每个人都有不同生活,没有一个人是平凡而简单的。

已做:30+

还剩:10+

期限:暂定


个人分类:(暂时做过的)

0-1 背包: 2602 2546 2955 1203


完全背包: 2191 1171 1248 1114


0-1 背包第k优解: 2639


多维背包: 2844(模板,二进制优化)


最优子序列:1003 1231

最长公共子序列:1159

最大上升子序列:1087

最长上升子序列:1257


贪心: 1789


简单dp:
2084(数塔) 1176(数塔变形) 2577  1421 

1224 1978 2845 1864 2159 1058


最大子矩阵 1505 1506 2870 2830


dp+dfs:
1078 2571


在已经做的题目里面,我是用txt存在电脑里的,按照hdu题号排序的结果就如下:


hdu 1003 Max Sum

// 最优子序列(和最大的连续子序列)
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define maxn 0xfffffff
int main()
{
    int t;
    scanf("%d",&t);
    int tag=0;
    while(t--)
    {
        int n;
        scanf("%d",&n);
        int sum=0,tmp=-maxn,cnt=0,start=1,end=1,a;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a);
            sum+=a;
            if(sum>tmp)
            {
                tmp=sum;
                start=cnt+1;
                end=i;
            }
            if(sum<0)
            {
                sum=0;
                cnt=i;
            }
        }
        printf("Case %d:\n%d %d %d\n",++tag,tmp,start,end);
        if(t)
            printf("\n");
    }
    return 0;
}


hdu 1058 Humble Numbers

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int num[5843];
int main()
{
    int  a=1,b=1,c=1,d=1;
    num[1]=1;
    for(int i=2;i<=5842;i++)
    {
        num[i]=min(min(num[a]*2,num[b]*3),min(num[c]*5,num[d]*7));
        if(num[i]==num[a]*2) a++;
        if(num[i]==num[b]*3) b++;
        if(num[i]==num[c]*5) c++;
        if(num[i]==num[d]*7) d++;
    }
    int n;
    while(scanf("%d",&n)!=EOF,n)
    {
        if(n%10==1&&n%100!=11)
            printf("The %dst humble number is %d.\n",n,num[n]);
        else if(n%10==2&&n%100!=12)
            printf("The %dnd humble number is %d.\n",n,num[n]);
        else if(n%10==3&&n%100!=13)
            printf("The %drd humble number is %d.\n",n,num[n]);
        else
            printf("The %dth humble number is %d.\n",n,num[n]);
    }
    return 0;
}


hdu 1059 Dividing

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int dp[120010];// 20000*6
int a[7];
int v;
void ZeroOne(int cost,int weight)
{
    for(int i=v;i>=cost;i--)
        dp[i]=max(dp[i],dp[i-cost]+weight);
}
void Complete(int cost,int weight)
{
    for(int i=cost;i<=v;i++)
        dp[i]=max(dp[i],dp[i-cost]+weight);
}
void Multiple(int cost,int weight,int count)
{
    if(cost*count>=v)
        Complete(cost,weight);
    else
    {
        int k=1;
        while(k<count)
        {
            ZeroOne(k*cost,k*weight);
            count-=k;
            k*=2;
        }
        ZeroOne(count*cost,count*weight);
    }
}
int main()
{
    int tmp=0;
    while(scanf("%d%d%d%d%d%d",&a[1],&a[2],&a[3],&a[4],&a[5],&a[6])!=EOF)
    {
        if(!(a[1]||a[2]||a[3]||a[4]||a[5]||a[6]))
            break;
        printf("Collection #%d:\n",++tmp);
        v=0;
        for(int i=1;i<=6;i++)
        {
            v+=a[i]*i;
        }
        if(v&1)
            printf("Can't be divided.\n");
        else
        {
            v/=2;
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=6;i++)
                Multiple(i,i,a[i]);
            if(dp[v]==v)
                printf("Can be divided.\n");
            else
                printf("Can't be divided.\n");
        }
        printf("\n");
    }
    return 0;
}


hdu 1069 Monkey and Banana

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
struct block
{
    int x,y,z;
}B[100];
int cnt[3];
int dp[100];
void init(block *B,int a,int b,int c)
{// 这个坑了我好久,突然想起之前写过一个很sb的swap
    B->x=max(a,b);
    B->y=min(a,b);
    B->z=c;
}
bool cmp(block p,block q)
{
    if(p.x==q.x)
        return p.y>q.y;
    return p.x>q.x;
}
int main()
{
    int n;
    int tag=0;
    while(scanf("%d",&n),n)
    {
        int tmp=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<3;j++)
                scanf("%d",&cnt[j]);
            init(&B[++tmp],cnt[2],cnt[1],cnt[0]);
            init(&B[++tmp],cnt[1],cnt[0],cnt[2]);
            init(&B[++tmp],cnt[2],cnt[0],cnt[1]);
        }
        sort(B+1,B+tmp+1,cmp);
        int ans=0;
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=tmp;i++)
        {
            int now=0;
            for(int j=i-1;j>=0;j--)
                if(B[i].x<B[j].x&&B[i].y<B[j].y)
                    now=max(now,dp[j]);
            dp[i]=B[i].z+now;
            ans=max(ans,dp[i]);
            //开始写的是直接输出dp[tmp],WA了,因为最后一组的三个可以不是按height排的
	    // 可以写 ans=max(dp[tmp],dp[tmp-1],dp[tmp-2])
        }
        printf("Case %d: maximum height = %d\n",++tag,ans);
    }
    return 0;
}


hdu 1078 FatMouse and Cheese

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int dp[110][110],map[110][110];
int move[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int n,k;
int dfs(int x,int y)
{
    if(dp[x][y])
        return dp[x][y];
    int temp=0;
    for(int i=0;i<4;i++)
        for(int j=1;j<=k;j++)
        {
            int xx=x+move[i][0]*j;
            int yy=y+move[i][1]*j;
            if(xx<=n&&xx>=1&&yy<=n&&yy>=1&&map[xx][yy]>map[x][y])
            {
                int cnt=dfs(xx,yy);
                temp=max(temp,cnt);
            }
        }
    dp[x][y]=temp+map[x][y];
    return dp[x][y];
}
int main()
{
    while(scanf("%d%d",&n,&k),n!=-1||k!=-1)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&map[i][j]);
                dp[i][j]=0;
            }
            printf("%d\n",dfs(1,1));
    }
    return 0;
}


hdu 1087 Super Jumping! Jumping! Jumping!

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[1010],v[1010];
int main()
{
    int n;
    while(scanf("%d",&n),n)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&v[i]);
            dp[i]=v[i];
            for(int j=1;j<i;j++)
                if(v[j]<v[i])
                    dp[i]=max(dp[i],dp[j]+v[i]);
        }
        int mi=0;
        for(int i=1;i<=n;i++)
            mi=max(mi,dp[i]);
        printf("%d\n",mi);
    }
    return 0;
}


hdu 1114 Piggy-Bank

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
int w[510],v[510];
int dp[10010];
int E,F,V;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&E,&F);
        V=F-E;
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&v[i],&w[i]);
        memset(dp,0x3f,sizeof(dp));
        int inf=dp[1];
        dp[0]=0;
        for(int i=1;i<=n;i++)
            for(int j=w[i];j<=V;j++)
                dp[j]=min(dp[j],dp[j-w[i]]+v[i]);
        if(dp[V]<inf)
            printf("The minimum amount of money in the piggy-bank is %d.\n",dp[V]);
        else
            printf("This is impossible.\n");
    }
    return 0;
}


hdu 1159 Common Subsequence

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
string s1,s2;
int dp[1000][1000];
int main()
{
    while(cin>>s1>>s2)
    {
	memset(dp,0,sizeof(dp));
        for(int i=1;i<=s1.size();i++)
            for(int j=1;j<=s2.size();j++)
            {
                if(s1[i-1]==s2[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("%d\n",dp[s1.size()][s2.size()]);
    }
    return 0;
}


hdu 1171 Big Event in HDU

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define maxn 125005
int dp[maxn];// 50种*50value*100kind/2
int v[55],kind[105];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF,n>=0)
    {
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&v[i],&kind[i]);
            ans+=v[i]*kind[i];
        }
        int tmp=ans/2;
        tmp=max(ans-tmp,tmp);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=kind[i];j++)
                for(int k=tmp;k>=v[i];k--)
                    dp[k]=max(dp[k],dp[k-v[i]]+v[i]);
        printf("%d %d\n",max(dp[tmp],ans-dp[tmp]),min(dp[tmp],ans-dp[tmp]));
    }
    return 0;
}


hdu 1176 免费馅饼

// 时间当做层数,馅饼当做数,就转换成数塔的题了
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[100010][12];
int main()
{
    int n;
    while(scanf("%d",&n),n!=0)
    {
        int a,b,tmp=0;
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&a,&b);
            dp[b][a]++;
            tmp=max(tmp,b);
        }
        for(int i=tmp-1;i>=0;i--)
        {
            dp[i][0]+=max(dp[i+1][0],dp[i+1][1]);
            for(int j=1;j<=10;j++)
                dp[i][j]+=max(dp[i+1][j-1],max(dp[i+1][j],dp[i+1][j+1]));
        }
        printf("%d\n",dp[0][5]);
    }
    return 0;
}


hdu 1203 I NEED A OFFER!

// 至少收到一份offer的(最大)概率
// 反命题就是 一份都没收到的(最小)概率

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
#define maxn 10001
double dp[maxn];
int v[maxn];
double p[maxn];
int main()
{
    int m,n;
    while(scanf("%d%d",&m,&n)!=EOF,m+n)
    {
        for(int i=1;i<=n;i++)
            scanf("%d%lf",&v[i],&p[i]);
        for(int i=0;i<=maxn;i++)//开始写的是从1开始,WA一次
            dp[i]=1;
        for(int i=1;i<=n;i++)
            for(int j=m;j>=v[i];j--)
                dp[j]=min(dp[j],dp[j-v[i]]*(1-p[i]));
        printf("%.1lf%%\n",(1-dp[m])*100);
    }
    return 0;
}


hdu 1224 Free DIY Tour

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int dp[105],v[105],father[105];
int map[105][105];
void show(int n)
{
    if(n==father[n])
        printf("%d",n);
    else
    {
        show(father[n]);
        printf("->%d",n);
    }
}
int main()
{
    int t,tag=0;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&v[i]);
            father[i]=i;
        }
        v[n+1]=0;
        memset(map,0,sizeof(map));
        int m,a,b;
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            map[a][b]=1;
        }
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n+1;i++)
            for(int j=1;j<i;j++)
            {
                if(map[j][i]&&dp[j]+v[i]>dp[i])
                {
                    dp[i]=dp[j]+v[i];
                    father[i]=j;
                }
            }
        printf("CASE %d#\n",++tag);
        printf("points : %d\n",dp[n+1]);
        printf("circuit : ");
        show(father[n+1]);
        printf("->1\n");
        if(t)
            printf("\n");
    }
    return 0;
}


hdu 1231 最大连续子序列

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=10001;
int a[maxn];
int main()
{
    int n;
    while(scanf("%d",&n),n)
    {
        int tag=0;
        int start=1,end=1,sum=0,tmp=0,mx=-0xfffffff;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            sum+=a[i];
            if(a[i]>=0)
                tag=1;
            if(sum>mx)
            {
                start=tmp+1;
                end=i;
                mx=sum;
            }
            if(sum<0)
            {
                tmp=i;
                sum=0;
            }
        }
        if(tag)
            printf("%d %d %d\n",mx,a[start],a[end]);
        else
            printf("0 %d %d\n",a[1],a[n]);
    }
    return 0;
}


hdu 1248 寒冰王座

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[10001];
int v[4]={0,150,200,350};
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=3;i++)
            for(int j=v[i];j<=n;j++)
                dp[j]=max(dp[j],dp[j-v[i]]+v[i]);
        printf("%d\n",n-dp[n]);
    }
    return 0;
}


hdu 1257 最少拦截系统

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=30010;
int dp[maxn];
int a[maxn];
int LIS(int *a,int n)
{
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=n;i++)
    {
        int tmp=dp[i];
        for(int j=1;j<i;j++)
        {
            if(tmp<dp[j]&&a[i]>a[j])
            {
                tmp=dp[j];
            }
        }
        dp[i]=tmp+1;
    }
    int ans=0;
    for(int i=1;i<=n;i++)
        ans=max(ans,dp[i]);
    return ans;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        printf("%d\n",LIS(a,n));
    }
    return 0;
}


hdu 1421 搬寝室

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int dp[2002][1001];
int v[2002];
int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&v[i]);
        sort(v+1,v+n+1);
        for(int i=1;i<n;i++)
        {
            v[i]=v[i+1]-v[i];
            v[i]*=v[i];
        }
        memset(dp,0x7f,sizeof(dp));
        // memset原本是用来处理字符串的,最大赋值为0x7f,对应一个10^10数量级的数
        for(int i=0;i<=n;i++)
            dp[i][0]=0;
        for(int i=2;i<=n;i++)
            for(int j=1;2*j<=i;j++)
                dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+v[i-1]);
        printf("%d\n",dp[n][k]);
    }
    return 0;
}


hdu 1505 City Game

// hdu2506的变形
// 看其中一排,把这排及下面的数中可以的“F”累计存在数组里
// 然后剩下的就是和hdu2506一样的步骤了
// 输入好坑 之前用%*c%c WA了,然后改用scanf(“%s”)过了
// 说明中间的空格可能不是连续的,不能默认为只有一个
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=1001;
char map[maxn][maxn];
int a[maxn];
int l[maxn],r[maxn];
int m,n;
int solve()
{
    l[1]=1;
    for(int i=2;i<=n;i++)
    {
        int tmp=i;
        while(tmp>1&&a[i]<=a[tmp-1])
            tmp=l[tmp-1];
        l[i]=tmp;
    }
    r[n]=n;
    for(int i=n-1;i>=1;i--)
    {
        int tmp=i;
        while(tmp<n&&a[i]<=a[tmp+1])
            tmp=r[tmp+1];
        r[i]=tmp;
    }
    int ans=0;
    for(int i=1;i<=n;i++)
        ans=max(ans,(r[i]-l[i]+1)*a[i]);
    return ans;
}
char str[10];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&m,&n);
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
            {
                scanf("%s",str);
                map[i][j]=str[0];
            }
        int ans=0;
        for(int i=1;i<=m;i++)
        {
            memset(a,0,sizeof(a));
            for(int k=1;k<=n;k++)
            {
                for(int j=i;j<=m;j++)
                {
                    if(map[j][k]=='F')
                        a[k]++;
                    if(map[j][k]=='R')
                        break;
                }
            }
            ans=max(ans,solve());
        }
        printf("%d\n",3*ans);
    }
    return 0;
}


hdu 1506 Largest Rectangle in a Histogram

// 把某根柱子周围能够延伸到的范围记下来(比旁边都要矮)
// 利用递归记录范围,避免大量的重复
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=100010;
long long a[maxn];
int r[maxn],l[maxn];
int main()
{
    int n;
    while(scanf("%d",&n),n)
    {
        for(int i=1;i<=n;i++)
            scanf("%I64d",&a[i]);
        l[1]=1;
        for(int i=2;i<=n;i++)
        {
            int tmp=i;
            while(tmp>1&&a[i]<=a[tmp-1])
                tmp=l[tmp-1];
            l[i]=tmp;
        }
        r[n]=n;
        for(int i=n-1;i>=1;i--)
        {
            int tmp=i;
            while(tmp<n&&a[i]<=a[tmp+1])
                tmp=r[tmp+1];
            r[i]=tmp;
        }
        long long ans=0;
        for(int i=1;i<=n;i++)
            ans=max(ans,(r[i]-l[i]+1)*a[i]);
        printf("%I64d\n",ans);
    }
    return 0;
}


hdu 1789 Doing Homework again

// 贪心
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
struct S
{
    int time,value;
};
S s[1010];
int vis[1010];
bool cmp(S a,S b)
{
    if(a.value==b.value)
        return a.time<b.time;
    return a.value>b.value;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&s[i].time);
        for(int i=1;i<=n;i++)
            scanf("%d",&s[i].value);
        sort(s+1,s+n+1,cmp);
        int ans=0;
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
        {
            if(!vis[s[i].time])
                vis[s[i].time]=1;
            else
            {
                int tag=0;
                for(int j=s[i].time;j>=1;j--)
                {
                    if(!vis[j])
                    {
                        vis[j]=1;
                        tag=1;
                        break;
                    }
                }
                if(!tag)
                {
                    for(int j=n;j>s[i].time;j--)
                    {
                        if(!vis[j])
                        {
                            vis[j]=1;
                            ans+=s[i].value;
                            break;
                        }
                    }
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}


hdu 1864 最大报销额

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
double v[31];
double dp[31];
int main()
{
    double M;
    int N;
    while(scanf("%lf%d",&M,&N),N)
    {
        for(int i=1;i<=N;i++)
        {
            int n;
            scanf("%d",&n);
            int tag=0;
            double value=0;
            int v_a=0,v_b=0,v_c=0;
            while(n--)
            {
                char c;
                double tmp;
                scanf("%*c%c:%lf",&c,&tmp);
                if(c>'C'||c<'A')
                    tag=1;
                value+=tmp;
                if(c=='A')
                    v_a+=tmp;
                if(c=='B')
                    v_b+=tmp;
                if(c=='C')
                    v_c+=tmp;
                if(value>1000||v_a>600||v_b>600||v_c>600)
                    tag=1;
            }
            if(tag)
                v[i]=0;
            else
                v[i]=value;
        }
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=N;i++)
            for(int j=i;j>=1;j--)
                dp[j]=max(dp[j],dp[j-1]+v[i]);
        double ans=0;
        for(int i=1;i<=N;i++)
            if(dp[i]<=M)
            {
                ans=max(ans,dp[i]);
            }
        printf("%.2lf\n",ans);
    }
    return 0;
}


hdu 1978 How many ways

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int dp[210][210];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int m,n;
        scanf("%d%d",&m,&n);
        memset(dp,0,sizeof(dp));
        dp[1][1]=1;
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
            {
                int cnt;
                scanf("%d",&cnt);
                for(int k=0;k<=cnt;k++)
                    for(int l=0;l+k<=cnt;l++)
                    {
                        if(l==0&&k==0)
                            continue;
                        dp[i+k][j+l]=(dp[i][j]+dp[i+k][j+l])%10000;
                    }
            }
        printf("%d\n",dp[m][n]);
    }
    return 0;
}


hdu 2084 数塔

// 简单dp
// 从倒数第二层开始往上走
// 将每个点左右节点中的最大值累计给自己往上传
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[110][110];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=i;j++)
                scanf("%d",&dp[i][j]);
        for(int i=n-1;i>=1;i--)
            for(int j=1;j<=n;j++)
                dp[i][j]+=max(dp[i+1][j],dp[i+1][j+1]);
        printf("%d\n",dp[1][1]);
    }
    return 0;
}


hdu 2159 FATE

// 二维背包
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int n,m,K,s;
int exp[101],tol[101];
int dp[101][101];
int main()
{
    while(scanf("%d%d%d%d",&n,&m,&K,&s)!=EOF)
    {
        int tag=0,ans;
        for(int i=1;i<=K;i++)
            scanf("%d%d",&exp[i],&tol[i]);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=s;j++)
            {
                for(int k=1;k<=K;k++)
                {
                    if(i>=tol[k])
                        dp[i][j]=max(dp[i][j],dp[i-tol[k]][j-1]+exp[k]);
                }
            }
            if(dp[i][s]>=n)
            {
                ans=m-i;
                tag=1;
                break;
            }
        }
        if(!tag)
            printf("-1\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}


hdu 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int dp[101],v[101],w[101],num[101];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int m,n;
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;i++)
            scanf("%d%d%d",&v[i],&w[i],&num[i]);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=num[i];j++)
                for(int k=m;k>=v[i];k--)
                    dp[k]=max(dp[k],dp[k-v[i]]+w[i]);
        printf("%d\n",dp[m]);
    }
    return 0;
}


hdu 2546 饭卡

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=1010;
int dp[maxn],a[maxn];
int main()
{
    int n;
    while(scanf("%d",&n),n)
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        int m;
        scanf("%d",&m);
        if(m<5)
            printf("%d\n",m);
        else
        {
            memset(dp,0,sizeof(dp));
            sort(a+1,a+n+1);
            for(int i=1;i<=n-1;i++)
                for(int j=m-5;j>=a[i];j--)
                    dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
            printf("%d\n",m-dp[m-5]-a[n]);
        }
    }
    return  0;
}


hdu 2571 命运

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int map[21][1001],vis[21][1001];
int m,n;
int dfs(int x,int y)
{
    if(vis[x][y]!=-1001)
        return vis[x][y];
    int tmp;
    if(x==1&&y==1)
        tmp=map[1][1];
    else if(y==1&&x>1)
        tmp=map[x][y]+dfs(x-1,y);
    else if(x==1&&y>1)
    {
        tmp=dfs(x,y-1);
        for(int k=y-1;k>=1;k--)
            if(y%k==0)
                tmp=max(tmp,dfs(x,k));
        tmp+=map[x][y];
    }
    else
    {
        tmp=max(dfs(x-1,y),dfs(x,y-1));
        for(int k=y-1;k>=1;k--)
            if(y%k==0)
                tmp=max(tmp,dfs(x,k));
        tmp+=map[x][y];
    }
    vis[x][y]=tmp;
    return vis[x][y];
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&map[i][j]);
                vis[i][j]=-1001;
            }
        printf("%d\n",dfs(n,m));
    }
    return 0;
}


hdu 2577 How to Type

#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string s;
int dp[110][2];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        cin>>s;
        memset(dp,0,sizeof(dp));
        dp[0][1]=1;// 表示开始是锁是开的
        for(int i=0;i<s.size();i++)
        {
            if(s[i]>='a'&&s[i]<='z')
            {
                dp[i+1][0]=min(dp[i][0]+1,dp[i][1]+2);
                dp[i+1][1]=min(dp[i][0]+2,dp[i][1]+2);
            }
            else
            {
                dp[i+1][0]=min(dp[i][0]+2,dp[i][1]+2);
                dp[i+1][1]=min(dp[i][0]+2,dp[i][1]+1);
            }
        }
        printf("%d\n",min(dp[s.size()][0],dp[s.size()][1]+1));
    }
    return 0;
}


hdu 2602 Bone Collector

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=1010;
int v[maxn],w[maxn];
int dp[maxn];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,V;
        scanf("%d%d",&n,&V);
        for(int i=1;i<=n;i++)
            scanf("%d",&w[i]);
        for(int i=1;i<=n;i++)
            scanf("%d",&v[i]);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
            for(int j=V;j>=v[i];j--)
                dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
        printf("%d\n",dp[V]);
    }
    return 0;
}


hdu 2639 Bone Collector II

// 0-1背包第k优解
// 将两个for里面的状态用队列标记起来
// 然后将这个有序队列进行合并(取(2k-2)项),取k时的情况
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1005;
int val[maxn],v[maxn];
int f[maxn][35];
int A[35],B[35];
int N,V,K;
void solve()
{
    int k;
    memset(f,0,sizeof(f));
    for(int i=1;i<=N;i++)
        for(int j=V;j>=v[i];j--)
        {
            for(k=1;k<=K;k++)
            {
                A[k]=f[j-v[i]][k]+val[i];
                B[k]=f[j][k];
            }
            A[k]=-1,B[k]=-1;//覆盖掉无所谓
            int a=1,b=1,c=1;
            while(c<=K&&(A[a]!=-1||B[b]!=-1))
            {
                if(A[a]>B[b])
                    f[j][c]=A[a++];
                else
                    f[j][c]=B[b++];
                if(f[j][c]!=f[j][c-1])
                    c++;
            }
        }
    printf("%d\n",f[V][K]);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&N,&V,&K);
        for(int i=1;i<=N;i++)
            scanf("%d",&val[i]);
        for(int i=1;i<=N;i++)
            scanf("%d",&v[i]);
        solve();
    }
    return 0;
}


hdu 2830 Matrix Swapping II

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=1010;
int map[maxn][maxn];
int tag[maxn];
char str[maxn][maxn];
int main()
{
    int m,n;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        memset(map,0,sizeof(map));
        for(int i=1;i<=m;i++)
            scanf("%s",str[i]);
        for(int i=1;i<=m;i++)
            for(int j=0;j<n;j++)
                if(str[i][j]=='1')
                    map[i][j+1]=map[i-1][j+1]+1;
                else
                    map[i][j+1]=0;
        int ans=0;
        for(int i=1;i<=m;i++)
        {
            memset(tag,0,sizeof(tag));
            for(int j=1;j<=n;j++)
                tag[map[i][j]]++;
            for(int j=i;j>=0;j--)
                tag[j]+=tag[j+1];//逆序,把比它高的累计起来
            for(int j=1;j<=i;j++)
                ans=max(ans,tag[j]*j);
        }
        printf("%d\n",ans);
    }
    return 0;
}
//还真的用空间换取了时间
//下面的代码用时间是前面的十倍 == 
// 空间就是少了那个char str[maxn][maxn] 
/*
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=1010;
int map[maxn][maxn];
int tag[maxn];
char str[maxn][maxn];
int main()
{
    int m,n;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        memset(map,0,sizeof(map));
        for(int i=1;i<=m;i++)
            scanf("%s",str[i]);
        for(int i=1;i<=m;i++)
            for(int j=0;j<n;j++)
                if(str[i][j]=='1')
                    map[i][j+1]=map[i-1][j+1]+1;
                else
                    map[i][j+1]=0;
        int ans=0;
        for(int i=1;i<=m;i++)
        {
            memset(tag,0,sizeof(tag));
            for(int j=1;j<=n;j++)
                tag[map[i][j]]++;
            for(int j=i;j>=0;j--)
                tag[j]+=tag[j+1];//逆序,把比它高的累计起来
            for(int j=1;j<=i;j++)
                ans=max(ans,tag[j]*j);
        }
        printf("%d\n",ans);
    }
    return 0;
}
*/


hdu 2844 Coins

// 擦,dp题竟然也用模板
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int dp[100010];
int a[1010],c[1010];
int v;
void ZeroOne(int cost,int weight)
{
    for(int i=v;i>=cost;i--)
        dp[i]=max(dp[i],dp[i-cost]+weight);
}
void Complete(int cost,int weight)
{
    for(int i=cost;i<=v;i++)
        dp[i]=max(dp[i],dp[i-cost]+weight);
}
void Multiple(int cost,int weight,int count)
{
    if(cost*count>=v)
        Complete(cost,weight);
    else
    {
        int k=1;
        while(k<count)
        {
            ZeroOne(k*cost,k*weight);
            count-=k;
            k*=2;
        }
        ZeroOne(count*cost,count*weight);
    }
}
int main()
{
    int m,n;
    while(scanf("%d%d",&n,&m),m||n)
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
            scanf("%d",&c[i]);
        memset(dp,0,sizeof(dp));
        v=m;
        for(int i=1;i<=n;i++)
            Multiple(a[i],a[i],c[i]);
        int ans=0;
        for(int i=1;i<=m;i++)//跟hdu big event那题一样,cost=weight,求最多能装到多少
            if(dp[i]==i)
                ans++;
        printf("%d\n",ans);
    }
    return 0;
}


hdu 2845 Beans

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=200010;
int a[maxn],b[maxn];
int main()
{
    int m,n;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        a[0]=b[0]=0;
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
                scanf("%d",&a[j]);
            for(int j=2;j<=n;j++)
                a[j]=max(a[j-1],a[j-2]+a[j]);
            b[i]=a[n];
        }
        for(int i=2;i<=m;i++)
            b[i]=max(b[i-1],b[i-2]+b[i]);
        printf("%d\n",b[m]);
    }
    return 0;
}


hdu 2870 Largest Submatrix

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1010;
int a[maxn],l[maxn],r[maxn];
int map[maxn][maxn];
char vis[maxn][maxn];
int solution(int col)
{
    l[1]=1;
    for(int i=2;i<=col;i++)
    {
        int tmp=i;
        while(tmp>1&&a[i]<=a[tmp-1])
            tmp=l[tmp-1];
        l[i]=tmp;
    }
    r[col]=col;
    for(int i=col-1;i>=1;i--)
    {
        int tmp=i;
        while(tmp<col&&a[i]<=a[tmp+1])
            tmp=r[tmp+1];
        r[i]=tmp;
    }
    int ans=0;
    for(int i=1;i<=col;i++)
        ans=max(ans,(r[i]-l[i]+1)*a[i]);
    return ans;
}
int solve(int row,int col)
{
    int ans=0;
    for(int i=1;i<=row;i++)
    {
        memset(a,0,sizeof(a));
        for(int k=1;k<=col;k++)
        {
            for(int j=i;j<=row;j++)
            {
                if(map[j][k]==1)
                    a[k]++;
                else
                    break;
            }
        }
        ans=max(ans,solution(col));
    }
    return ans;
}
int main()
{
    int m,n;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        int ans=0;
        for(int i=1;i<=m;i++)
            scanf("%s",vis[i]);
        for(int i=1;i<=m;i++)
            for(int j=0;j<n;j++)
                if(vis[i][j]=='x'||vis[i][j]=='b'||vis[i][j]=='c')
                    map[i][j+1]=0;
                else
                    map[i][j+1]=1;
        ans=max(ans,solve(m,n));
        for(int i=1;i<=m;i++)
            for(int j=0;j<n;j++)
                if(vis[i][j]=='y'||vis[i][j]=='a'||vis[i][j]=='c')
                    map[i][j+1]=0;
                else
                    map[i][j+1]=1;
        ans=max(ans,solve(m,n));
        for(int i=1;i<=m;i++)
            for(int j=0;j<n;j++)
                if(vis[i][j]=='w'||vis[i][j]=='a'||vis[i][j]=='b')
                    map[i][j+1]=0;
                else
                    map[i][j+1]=1;
        ans=max(ans,solve(m,n));
        printf("%d\n",ans);
    }
    return 0;
}


hdu 2955 Robberies

// 给定抢多少钱不被抓的概率
// 求给定概率内能抢到的最多钱(最大概率不被抓)
// 反命题就是钱尽量多,被抓的最大概率
//  attention: init dp[0]=1;else dp[i]=0;
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=10010;
int v[maxn],n;
double dp[maxn],p[maxn],P;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int sum=0;
        scanf("%lf%d",&P,&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%lf",&v[i],&p[i]);
            sum+=v[i];
        }
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        for(int i=1;i<=n;i++)
            for(int j=sum;j>=v[i];j--)
                dp[j]=max(dp[j],dp[j-v[i]]*(1-p[i]));
        for(int i=sum;i>=0;i--)
            if(dp[i]>=1-P)
            {
                printf("%d\n",i);
                break;
            }
    }
    return 0;
}


还剩下:

hdu 1024 Max Sum Plus Plus

hdu 1081 To The Max

hdu 1025 Constructing Roads In JGShining's Kingdom

hdu 2059 龟兔赛跑

hdu 1158 Employment Planning

hdu 1080 Human Gene Functions

hdu 1160 FatMouse's Speed

hdu 1074 Doing Homework

hdu 1422 重温世界杯

hdu 1300 Pearls

hdu 1501 Zipper

hdu 1227 Fast Food

hdu 3008 Warcraft

hdu 1502 Regular Words

hdu 1503 Advanced Fruits


屌丝嘛,平时多笑笑就好,开开心心的,csdn论坛上的屌丝传奇,推荐大家去乐乐:

【转】传奇(诞生篇) 

【转】传奇(围观篇)



当然,剩下的还是应该逐步击破,但一定不可以为了做题而强迫自己看别人的代码从而A掉。

其实,我一直在纠结强迫自己是好事还是坏事,但从长远的看来,有些问题还是很明显的。

总有一个人,你骗得了全世界也不舍得骗,那个人就是我们自己。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值