8月7号的练习:HDU 1069&&POJ 1636&&HDU 1031&&HDU 1051&&HDU 1551
题意:有n(n<=30)种不同的立方体(每种个数不限), 求能够堆多高.
分析:
(1) 对于每一种立方体, 假设长,宽,高互不相等, 则它放置方法有6种不同的情况(长,宽,高全排列).
(2)那么,实际上可以看成是6*n种不同的立方体.
(3)对这6*n种立方体的长(如果长相等则以宽)小到大排序.
(4)这里就等效于有很多的箱子排成了一列, 看怎么才能将它堆得最高,
(5)从小的一边开始, 如果后面的箱子上面能放下前面较小的, 就放一个那种小的到那些大箱子上.
(6)然后将这一堆看成一个箱子,只是这个箱子比以前加高了,但底面还是不变.
(7)重复(6)的操作. 直到最后没有任何位置的箱子可以放到其位置的箱子上面时, 找到最高的那个就是答案!
1 #include<iostream> 2 #include<algorithm> 3 #include<stdio.h> 4 using namespace std; 5 struct line 6 { 7 int x; 8 int y; 9 int z; 10 }a[200]; 11 bool comp1(line i,line j) 12 { 13 if(i.x!=j.x) 14 return i.x<j.x; 15 return i.y<j.y; 16 } 17 int main() 18 { 19 int n,i,a1,a2,a3,MAX,temp,j,d=0; 20 while(scanf("%d",&n)!=EOF) 21 { 22 if(n==0) 23 break; 24 for(i=1;i<=n;i++) 25 { 26 scanf("%d%d%d",&a1,&a2,&a3); 27 a[i*6].x =a1;a[i*6].y =a2;a[i*6].z =a3; 28 a[i*6-1].x=a2;a[i*6-1].y=a1;a[i*6-1].z=a3; 29 a[i*6-2].x=a1;a[i*6-2].y=a3;a[i*6-2].z=a2; 30 a[i*6-3].x=a3;a[i*6-3].y=a1;a[i*6-3].z=a2; 31 a[i*6-4].x=a3;a[i*6-4].y=a2;a[i*6-4].z=a1; 32 a[i*6-5].x=a2;a[i*6-5].y=a3;a[i*6-5].z=a1; 33 } 34 sort(a+1,a+1+6*n,comp1); 35 MAX=0; 36 for(i=1;i<=6*n;i++) 37 { 38 temp=0; 39 for(j=1;j<=i;j++) 40 if(a[i].x>a[j].x&&a[i].y>a[j].y) 41 temp=max(temp,a[j].z); 42 a[i].z+=temp; 43 if(a[i].z>MAX) 44 MAX=a[i].z; 45 }//这里从最小开始找,好理解的; 46 printf("Case %d: maximum height = %d\n",++d,MAX); 47 } 48 return 0; 49 }
这个题目怎么能是搜索和DP的综合呢(这个都没学通的。。。)
之后俩水题:
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<string.h> 5 using namespace std; 6 struct line 7 { 8 double x; 9 int y; 10 }b[105]; 11 bool comp1(line i,line j) 12 { 13 if(i.x!=j.x) return i.x>j.x; 14 return i.y<j.y; 15 } 16 bool comp2(line i,line j) 17 { 18 return i.y>j.y; 19 } 20 int main() 21 { 22 int n,m,t,i,j; 23 double a[105][105]; 24 while(scanf("%d%d%d",&n,&m,&t)!=EOF) 25 { 26 memset(b,0,sizeof(b)); 27 for(i=1;i<=n;i++) 28 for(j=1;j<=m;j++) 29 scanf("%lf",&a[i][j]); 30 for(j=1;j<=m;j++) 31 { 32 for(i=1;i<=n;i++) 33 b[j].x+=a[i][j]; 34 b[j].y=j; 35 } 36 sort(b+1,b+1+m,comp1); 37 sort(b+1,b+1+t,comp2); 38 for(i=1;i<=t-1;i++) 39 printf("%d ",b[i].y); 40 printf("%d\n",b[t].y); 41 } 42 return 0; 43 }
这个算是有公式了吧:(HDU 1677这个题差不多)
#include<iostream> #include<stdio.h> #include<algorithm> using namespace std; struct line { int x; int y; }a[5005]; bool comp1(line i,line j) { if(i.x!=j.x) return i.x>j.x; return i.y>j.y; } int main() { int dp[5005],t,n,i,j,MAX; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=0;i<n;i++) scanf("%d%d",&a[i].x,&a[i].y); sort(a,a+n,comp1); MAX=0; for(i=0;i<n;i++) { dp[i]=1; for(j=0;j<i;j++) if(a[i].y>a[j].y&&dp[i]<dp[j]+1) dp[i]=dp[j]+1; if(dp[i]>MAX) MAX=dp[i]; } printf("%d\n",MAX); } return 0; }
最后是一道二分题: Cable master HDU 1551
传说这类题以长,难懂,啰嗦叱咤于算法界!
还有他特有的技能:卡精度。不知卡死多少人!
题意:需要K根长度相等的电缆线 从已有的N条电缆线中剪切得来 求最长能获得多长的电缆线
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 using namespace std; 5 int main() 6 { 7 double s,a[10005]; 8 int n,m,k,i; 9 double l,r,mid; 10 while(scanf("%d%d",&n,&m)!=EOF) 11 { 12 if(n==0&&m==0) 13 break; 14 s=0; 15 for(i=0;i<n;i++) 16 { 17 scanf("%lf",&a[i]); 18 s+=a[i]; 19 } 20 if(s/m<1) 21 { 22 printf("0.00\n"); 23 continue; 24 } 25 l=0;r=s/m;mid=0; 26 while(r-l>1e-9) 27 { 28 k=0; //k要定义为整数,因为绳子没有半根的 29 mid=(l+r)/2; 30 for(i=0;i<n;i++) 31 k+=a[i]/mid; 32 if(k>=m) 33 l=mid; 34 else 35 r=mid; 36 } 37 printf("%.2lf\n",mid); 38 } 39 return 0; 40 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步