觉得浮夸了四年,漠然发现原来是浮躁了四年!

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!

复制代码
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久没有刷背包题了,比赛时,居然把它当做贪心猛做了好久!泪奔啊!

复制代码
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的特性!

复制代码
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 }
复制代码

 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,重新定义开始的位置开始统计。

复制代码
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背包问题,模板!

复制代码
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做的第一题!经典!

复制代码
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

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

复制代码
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 }
复制代码

 

 

posted @   heat nan  阅读(251)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示