HDOJ 2391

http://acm.hdu.edu.cn/showproblem.php?pid=2391

简单的DP dp[i][j] = max { dp[i-1][j], dp[i][j-1],dp[i-1][j-1] } + val[i][j];

 代码如下:
1 #include<iostream>
2  using namespace std;
3  int dp[1001][1001];
4 #include<algorithm>//max()函数返回较大值
5  int main(){
6 int t;cin>>t;
7 int m,n;
8 for(int i=1;i<=t;i++){
9 cin>>m>>n;
10 //初始化边界
11   for(int j=0;j<=1000;j++)
12 dp[j][0]=dp[0][j]=0;
13 for(int j=1;j<=m;j++)
14 for(int k=1;k<=n;k++)
15 //cin>>map[j][k];
16 //改变输入后,时间由1700ms变为300ms...
17   scanf("%d",&dp[j][k]);
18 int tempMax,map;
19 for(int j=1;j<=m;j++)
20 for(int k=1;k<=n;k++){
21 map=dp[j][k];
22 //找三者间最大值
23 dp[j][k]=max(map+dp[j][k-1]
24 ,map+dp[j-1][k]);
25 dp[j][k]=max(map+dp[j-1][k-1],dp[j][k]);
26 }
27 cout<<"Scenario #"<<i<<":"<<endl<<dp[m][n]<<endl<<endl;
28 }
29 return 0;
30 }

HDOJ 1069

题目大意,给定n中木块,分别给长宽高,问最高能垒多高,要求上面的木块长宽都要比下面的小。

DP:由于每一种木块数量无限,但实际上,每一种木块最多使用三次,所以每一种木块都当三个木块存储。

     再按底面积大小从大到小排一下序。

   最优子状态设定:box[i].max为以第i个木块为顶所能达到的最大高度。

则DP公式为:box[i].max = MAX{box[j].max}+box[i].height;    (0<=j<i , 并且MAX{}木块要容得下box[i])

第一次提交有错误,原因在多了第38句,break;实际上,排序只是按照底面积排的序,所以box[j].max并不是按照从自底向上

从小到大排的,比如,特殊化一下,一个面积特别小的细长型棍子,虽然排在了最后面,比如box[j(=i-1)],但是它并不一定能磊

到最上面,太长了,下面的容不下他,所以单独一个的话,box[j(=i-1)].max就很小了,所以得全部搜索一遍

View Code
1 #include<iostream>
2 #include<algorithm>
3 using namespace std;
4 struct Box{
5 int length;
6 int width;
7 int height;
8 int max;
9 };
10 bool comp(Box a,Box b){
11 return a.length*a.width>b.length*b.width;
12 }
13 bool isSuit(Box a,Box b){
14 return a.length<b.length&&a.width<b.width
15 || a.length<b.width&&a.width<b.length;
16 }
17
18 Box box[100];
19 int main(){
20 int n,l,w,h,t=1;
21 while(cin>>n&&n!=0){
22 for(int i=0;i<3*n;i++){
23 cin>>l>>w>>h;
24 box[i].height=l;box[i].width=w;box[i].length=h;i++;
25 box[i].height=w;box[i].width=l;box[i].length=h;i++;
26 box[i].height=h;box[i].width=l;box[i].length=w;
27 }
28 sort(box,box+3*n,comp);
29
30 box[0].max=box[0].height;
31 int tempmax=box[0].max;
32 for(int i=1;i<3*n;i++){
33 box[i].max=box[i].height;
34 for(int j=i-1;j>=0;j--){
35 if(!isSuit(box[i],box[j]))continue;
36 else if(box[i].max<box[j].max+box[i].height)
37 box[i].max=box[j].max+box[i].height;
38 //break;
39 }
40 if(box[i].max>tempmax)tempmax=box[i].max;
41 }
42 cout<<"Case "<<t++<<": maximum height = "<<tempmax<<endl;
43 }
44 return 0;
45 }

HDOJ 2512

http://acm.hdu.edu.cn/showproblem.php?pid=2512

题目大意:给定n张不同的卡,放到相同的书中,问多少种方法。如果,三张卡的话有五种如:

{{A},{B},{C}} , {{A,B},{C}}, {{B,C},{A}}, {{A,C},{B}} ,{{A,B,C}}

两张卡的话,两种:{{A}{B}}  {{A,B}}

状态设定:dp[i][j]为i张卡放到j本书的种类数。那么dp[i][j]=dp[i-1][j-1]*1+dp[i-1][j]*j

公式的前半部分:dp[i-1][j-1]*1表示第i张卡单独放到一本书中;

后半部分表示:dp[i-1][j]第j本书放到j堆中的其中一堆

状态临界值:当i=j时,dp[i][j]=1;

         当j=1时,dp[i][j]=1;

i 张卡的方法则为dp[i][1]+dp[i][2]+dp[i][3]...dp[i][i]

由此可以总结:应用dp时,矛头不一定指向问题的直接解,可以巧设状态变量,求的最终的解!

1 #include<iostream>
2 using namespace std;
3 int dp[2010][2010], res[2010], T, N;
4 void DP () {
5 dp[1][1] = 1, res[1] = 1;
6 for ( int i = 2; i <= 2000; ++ i ) {
7 dp[i][1] = dp[i][i] = 1, res[i] = 2;
8 for ( int j = 2; j < i; ++ j ) {
9 res[i] += dp[i][j] = ( dp[i-1][j-1] + dp[i-1][j] * j ) % 1000;
10 }
11 res[i] %= 1000;
12 }
13 }
14
15 int main ()
16 {
17 DP ();
18 scanf ( "%d", &T );
19 while ( T -- ) {
20 scanf ( "%d", &N );
21 printf ( "%d\n", res[N] );
22 }
23 return 0;
24 }
posted on 2011-04-28 03:13  geeker  阅读(488)  评论(0编辑  收藏  举报