hdu dp problems

Now, this article is for hdu dp problems!   Come on !

hdu 2391 Filthy Rich  Problem link adress:http://acm.hdu.edu.cn/showproblem.php?pid=2391

This problem is silimar to one of the problem in the province contest,so cleared it successfully!

In a world, it's a good problem!

hdu dp problems View Code
 1 #include<iostream>

 2 #include<cstring>

 3 #include<cstdio>

 4 #include<cstring>

 5 using namespace std;

 6 int t;

 7 int n,m;

 8 int map[1005][1005];

 9 int ans[1005][1005];

10 int max(int a,int b,int c)

11 {

12     int big;

13     big=a>b?a:b;

14     big=c>big?c:big;

15     return big;

16 }

17 int main()

18 {

19      int flag=1;

20      cin>>t;

21      while(t--)

22      {

23          cin>>n>>m;

24          int i,j;

25          memset(map,0,sizeof(map));

26          memset(ans,0,sizeof(ans));

27          for(i=1;i<=n;i++)

28              for(j=1;j<=m;j++)

29               cin>>map[i][j];

30          for(i=2;i<=n+1;i++)

31              for(j=2;j<=m+2;j++)

32              {

33                  ans[i][j]=max(ans[i-1][j]+map[i-1][j-1],ans[i][j-1]+map[i-1][j-1],ans[i-1][j-1]+map[i-1][j-1]);

34              }

35     

36            printf("Scenario #%d:\n",flag++);

37         cout<<ans[n+1][m+1]<<endl<<endl;

38      }

39      return 0;

40 }

41          

 

hdu  4508 (完全背包)     湫湫系列故事  减肥记I http://acm.hdu.edu.cn/showproblem.php?pid=4508

多重背包问题,N久没有刷背包题了,比赛时,居然把它当做贪心猛做了好久!泪奔啊!

hdu dp problems View Code
 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 using namespace std;

 5 #define N 105

 6 int n;

 7 int x[N],y[N];

 8 int dp[100005];

 9 int len;

10 int main()

11 {

12     int i,j;

13     while(scanf("%d",&n)!=EOF)

14     {

15         memset(x,0,sizeof(x));

16         memset(y,0,sizeof(y));

17         for(i=0;i<n;i++)

18             scanf("%d%d",&x[i],&y[i]);

19         scanf("%d",&len);

20         memset(dp,0,sizeof(dp));

21         for(i=0;i<n;i++)

22             for(j=0;j<=len;j++)

23             {

24                 if(j<y[i]) continue;//这一点很重要啊

25                 if(dp[j]<dp[j-y[i]]+x[i])

26                     dp[j]=dp[j-y[i]]+x[i];

27             }

28             printf("%d\n",dp[len]);

29     }

30     return 0;

31 }

 

hdu 4502 (dp)    吉哥系列故事--临时工计划   http://acm.hdu.edu.cn/showproblem.php?pid=4502

这一题有必要做个详细的分析了;

Problem Description
  俗话说一分钱难倒英雄汉,高中几年下来,吉哥已经深深明白了这个道理,因此,新年开始存储一年的个人资金已经成了习惯,不过自从大学之后他不好意思再向大人要压岁钱了,只能把唯一的希望放到自己身上。可是由于时间段的特殊性和自己能力的因素,只能找到些零零碎碎的工作,吉哥想知道怎么安排自己的假期才能获得最多的工资。
  已知吉哥一共有m天的假期,每天的编号从1到m,一共有n份可以做的工作,每份工作都知道起始时间s,终止时间e和对应的工资c,每份工作的起始和终止时间以天为单位(即天数编号),每份工作必须从起始时间做到终止时间才能得到总工资c,且不能存在时间重叠的工作。比如,第1天起始第2天结束的工作不能和第2天起始,第4天结束的工作一起被选定,因为第2天吉哥只能在一个地方工作。
  现在,吉哥想知道怎么安排才能在假期的m天内获得最大的工资数(第m+1天吉哥必须返回学校,m天以后起始或终止的工作是不能完成的)。

Input
第一行是数据的组数T;每组数据的第一行是2个正整数:假期时间m和可做的工作数n;接下来n行分别有3个正整数描述对应的n个工作的起始时间s,终止时间e,总工资c。

[Technical Specification]
1<=T<=1000
9<m<=100
0<n<=1000
s<=100, e<=100, s<=e
c<=10000

Output
对于每组数据,输出吉哥可获得的最高工资数。

Sample Input
1
10 5
1 5 100
3 10 10
5 10 100
1 4 2
6 12 266

 

这个问题用贪心做了很久,发现行不通,估计需要用动态规划!但是这题递归方程不是很好想!

循环方程仍分为两层,第一层循环工作,第二层循环时间;(对于每一个工作都记录从1-m天的结果)

那么对第i个工作来说,如果当前的天数j满足j小于工作i的结束时间,那么他将得不到工作i的工资,所以有:dp[i][j]=dp[i-1][j];

    如果满足dp[i-1][s[i].s-1]+s[i].p>dp[i-1][j];如果当前工作i所得的工资加上dp[i-1][s[i].s-1]的和大于dp[i-1][j],那么就更新,否则仍有dp[i][j]=dp[i-1][j]!

最后所得的dp[n][m]即为所求的值!

ps: DP是一个动态的记录最有answer的表格,在这个表格中,当前的循环总要借助于上一层的成果,层层递进,知道最后的最终解出现!

下面的代码中加入了结果显示,更好的显示了dp的特性!

hdu dp problems View Code
 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 using namespace std;

 6 int t;

 7 int m,n;

 8 int dp[1005][105];

 9 struct node{

10     int s,e,p;

11 }s[1005];

12 bool cmp(node a,node b)

13 {

14     return a.s<b.s;

15 }

16 int main()

17 {

18     int i,j;

19     scanf("%d",&t);

20     while(t--)

21     {

22         scanf("%d%d",&m,&n);

23         for(i=1;i<=n;i++)

24             scanf("%d%d%d",&s[i].s,&s[i].e,&s[i].p);

25 

26         printf("\n");

27 

28         sort(s+1,s+n+1,cmp);

29 //显示排序结果

30         for(i=1;i<=n;i++)

31             printf("%d %d %d\n",s[i].s,s[i].e,s[i].p);

32         printf("\n");

33 

34         memset(dp,0,sizeof(dp));

35         for(j=0;j<=m;j++)

36         {

37             if(j<s[1].e)

38                 dp[1][j]=0;

39             else

40                 dp[1][j]=s[1].p;

41         }

42         for(i=2;i<=n;i++)

43             for(j=1;j<=m;j++)

44             {

45                 if(s[i].e>j)

46                     dp[i][j]=dp[i-1][j];

47                 else if(dp[i-1][s[i].s-1]+s[i].p>dp[i-1][j])

48                     dp[i][j]=dp[i-1][s[i].s-1]+s[i].p;

49                 else

50                     dp[i][j]=dp[i-1][j];

51             }

52 //显示dp后的结果

53         for(i=1;i<=n;i++)

54         {

55             for(j=1;j<=m;j++)

56                 printf("%d ",dp[i][j]);

57             printf("\n");

58         }

59 

60             printf("\n");    

61 

62             printf("%d\n",dp[n][m]);

63     }

64     return 0;

65 }

hdu dp problems

 post by heat_nan@  2013-03-23  14:51  

DP去年草草学了两天就没管了,当时好像很难理解,大部分题都是囫囵吞枣!现在有必要好好复习一下,加深边理解了!

hdu 1003           Max  Sum                        http://acm.hdu.edu.cn/showproblem.php?pid=1003 

给定一串数字,计算最大的连续和,输出该最大子串的最大值和起始位置.

思路:设sum为当前状态的最大值,max为整个过程连续字串的最大值,转移状态方程:
如果sum+num[i]大于max,则更新max和起始位置的值,如果小于或者等于,不做处理,若果sum的当前值小于0时,那么需要令sum=0,重新定义开始的位置开始统计。

hdu dp problems View Code
 1 #include<iostream>

 2 #include<cstring>

 3 #include<cstdio>

 4 using namespace std;

 5 int t;

 6 int n;

 7 int num[100005];

 8 int main()

 9 {

10     int i;

11     scanf("%d",&t);

12     int c=1;

13     while(t--)

14     {

15         scanf("%d",&n);

16         memset(num,0,sizeof(num));

17         int b,e;

18         for(i=0;i<n;i++)

19             scanf("%d",&num[i]);

20         int sum=0;

21         int max=-9999;

22         int flag=1;

23         for(i=0;i<n;i++)

24         {

25             sum+=num[i];

26             if(sum>max)

27             {

28                 max=sum;

29                 b=flag;

30                 e=i+1;

31             }

32             if(sum<0)

33             {

34                 sum=0;

35                 flag=i+2;

36                 

37             }

38 

39         }

40         printf("Case %d:\n%d %d %d\n",c++,max,b,e);

41         if(t!=0)  printf("\n");

42     }

43     return 0;

44 }

45             

 

 

hdu 2602 bone collector     http://acm.hdu.edu.cn/showproblem.php?pid=2602 

经典赤裸裸的01背包问题,模板!

hdu dp problems View Code
 1 #include<iostream>

 2 #include<cstring>

 3 #include<cstdio>

 4 using namespace std;

 5 int dp[1005];

 6 int a[1005],b[1005];

 7 int n,v;

 8 int t;

 9 int max(int a,int b)

10 {

11     return a>b?a:b;

12 }

13 int main()

14 {

15     int i,j;

16     scanf("%d",&t);

17     while(t--)

18     {

19         scanf("%d%d",&n,&v);

20         memset(a,0,sizeof(a));

21         memset(b,0,sizeof(b));

22         memset(dp,0,sizeof(dp));

23         for(i=0;i<n;i++)

24             scanf("%d",&a[i]);

25         for(j=0;j<n;j++)

26             scanf("%d",&b[j]);

27         for(i=0;i<n;i++)

28         {

29             for(j=v;j>=b[i];j--)

30             {

31                   dp[j]=max(dp[j],dp[j-b[i]]+a[i]);

32             }

33         }

34     //    for(i=1;i<=v;i++)

35     //        printf("%d ",dp[i]);

36         printf("%d\n",dp[v]);

37 

38     }

39     return 0;

40 }

 

 

hdu 2084 dp经典数塔  http://acm.hdu.edu.cn/showproblem.php?pid=2084    

学习dp做的第一题!经典!

hdu dp problems View Code
 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 using namespace std;

 5 int t;

 6 int h;

 7 int map[105][105];

 8 int dp[105][105];

 9 int max(int a,int b)

10 {

11     return a>b?a:b;

12 }

13 int main()

14 {

15     int i,j;

16     scanf("%d",&t);

17     while(t--)

18     {

19         scanf("%d",&h);

20         for(i=0;i<h;i++)

21             for(j=0;j<=i;j++)

22                 scanf("%d",&map[i][j]);

23             memset(dp,0,sizeof(dp));

24         for(i=h-1;i>=0;i--)

25             for(j=0;j<=i;j++)

26             {

27                 dp[i][j]=max(dp[i+1][j]+map[i][j],dp[i+1][j+1]+map[i][j]);

28             }

29 

30         //for(i=0;i<h;i++)

31         //{

32         //    for(j=0;j<=i;j++)

33         //        printf("%d ",dp[i][j]);

34         //    printf("\n");

35         //}

36 

37 

38         printf("%d\n",dp[0][0]);

39     }

40     return 0;

41 }

 

 hdu 1711   Big Event in HDU   http://acm.hdu.edu.cn/showproblem.php?pid=1171 背包

有t种物品,每种物品n个,价值为v,把这些东西分为两部分,要求两部分的价值尽可能相等,如果无法保证相等,一部分的值不能小于另一部分。

详细分析:   http://www.cnblogs.com/heat-man/archive/2013/03/02/2940391.html

唯一不知道就是为什么注释掉的那种输出方式是错误的。

hdu dp problems View Code
 1 #include<iostream>

 2 #include<cstring>

 3 #include<cstdio>

 4 #include<algorithm>

 5 using namespace std;

 6 #define N 250000

 7 #define M 55

 8 int dp[N];

 9 int n[M],v[M];

10 int max(int a,int b)

11 {

12     if(a>b)

13         return a;

14     else

15         return b;

16 }

17 int main()

18 {

19 

20     int  t;

21     while(cin>>t)

22     {

23         if(t<0)   break;

24         memset(n,0,sizeof(n));

25         memset(v,0,sizeof(v));

26         int i,j,k;

27         int sum=0;

28         for(i=0;i<t;i++)

29         {

30 

31             cin>>v[i]>>n[i];

32             sum+=v[i]*n[i];

33         }

34         int all=sum;

35         sum/=2;

36         memset(dp,0,sizeof(dp));

37         for(i=0;i<t;i++)

38             for(j=1;j<=n[i];j++)

39               for(k=sum;k>=v[i];k--)

40         {

41               dp[k]=max(dp[k-v[i]]+v[i],dp[k]);

42         }

43        // if(dp[sum]>=sum)

44        // cout<<dp[sum]<<" "<<all-dp[sum]<<endl;

45        // else

46        //     cout<<all-dp[sum]<<" "<<dp[sum]<<endl;

47         int rest=all-dp[sum];

48         if(dp[sum]<rest)

49            swap(dp[sum],rest);

50         cout<<dp[sum]<<" "<<rest<<endl;

51 

52     }

53     return 0;

54 }

 

 

你可能感兴趣的:(HDU)