hdu_1069_Monkey and Banana
http://acm.hdu.edu.cn/showproblem.php?pid=1069
天花板上挂着一些香蕉,Monkey想要吃(Monkey不够高),于是Monkey想利用n个石块中的一些(长方体形状)堆起来,每层的石块的长和宽都要比前面一层的小(不可相等),这样Monkey才能爬上去,石块不限量。
考虑到石块可以转,所以每种石块有3种有效状态(如 10*20*30的石块,三种有效状态的长宽高分别是 30*20*10、30*10*20、20*10*30);由此也可以知道一种石块不可能使用超过3次。所以我们可以当做有3*n种不可转的石块。
首先进行排序,按长宽从大到小排序。
dp[i] 表示以第i种石块作为顶的最高可以有多高。我们要在前i-1种情况下找出能放下第i种石块的最高的情况。
dp[i]=max(dp[0...i-1]+s) //s为第i种石块的高。(==加了一个石块表示地面,即长宽等于INF,高为0,这样所有的石块都可以放置在这个”地面石块上面“)
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define INF 100000000 struct Node { int x,y,z; void set (int X,int Y,int Z){ x = X; y = Y; z = Z; } }; bool cmp (Node a,Node b){ if (a.x==b.x) return a.y>b.y; else return a.x>b.x; } int main(){ int n;int c=1; while (cin>>n,n){ int a[3]; Node s[200]; int dp[200]; memset (dp,0,sizeof(dp)); for (int i=0;i<n;i++){ for (int j=0;j<3;j++) cin>>a[j]; sort(a,a+3); s[i*3+0].set(a[2],a[1],a[0]); s[i*3+1].set(a[2],a[0],a[1]); s[i*3+2].set(a[1],a[0],a[2]); } s[n*3].set(INF,INF,0); sort (s,s+n*3+1,cmp); dp[0]=0; int t; for (int i=1;i<=3*n;i++){ t=0; for (int j=i-1;j>=0;j--){ if (s[j].x>s[i].x&&s[j].y>s[i].y){ if (dp[t]<dp[j]){ t=j; } } } dp[i]=dp[t]+s[i].z; } for (int i=1;i<=3*n;i++){ dp[0]=max(dp[0],dp[i]); } cout<<"Case "<<c++<<": maximum height = "<<dp[0]<<endl; } }
hdu_1078_FatMouse and Cheese
http://acm.hdu.edu.cn/showproblem.php?pid=1078
FatMouse 在一些存放了奶酪的”网格“里(位置<0,0>),因为外面有只猫,说以FatMouse每次最多只能走k步,当然,FatMouse可以往上下左右四个方向走。FatMouse每到一个网格就要吃掉网格里的奶酪,为了维持能量,FatMouse每次吃的奶酪都要比上一次吃的大。求FatMouse最多能吃多少奶酪。
看着像求一个最大和上升子序列,可是是二维的。wiking 说的把坐标存起来换成一维的。
结构体存奶酪大小和坐标(x,y),按奶酪大小排序,比(0,0)位置小的奶酪就不用理他了。
dp[i][j]表示以第[i][j]奶酪为最后吃的的最大值。dp[i][j]=max(dp[x][y]+a[i][j]);(dp[x][y]<a[i][j]) [x][y] 是可以走到ij的位置,有4个方向最多4*k个位置。
==这样我一直wa,因为即使a[i][j]>a[0][0],还是有可能没有(x,y)可以到达他的,不删除的话就会多一个起点。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; struct Node { int v,x,y; }; bool cmp (Node a,Node b){ return a.v<b.v; } int main (){ int n,k; while (cin>>n>>k){ if (n==-1&&k==-1){ break; } int a[106][106],v=0; int dp[106][106]; int use[106][106]; memset(dp,0,sizeof(dp)); memset(use,0,sizeof(use)); Node s[10010]; for (int i=0;i<n;i++){ for (int j=0;j<n;j++){ scanf ("%d",&a[i][j]); s[v].x=i;s[v].y=j; s[v].v=a[i][j]; v++; } } int ans=a[0][0],i; // cout<<v<<endl; sort (s,s+v,cmp); for (i=0;i<v;i++){ if (s[i].x==0&&s[i].y==0) { dp[0][0]=a[0][0];i++; break; } use[s[i].x][s[i].y]=1; } // cout<<s[i].x<<" "<<s[i].y<<endl; for (i;i<v;i++){ int X,Y,maxn=-1; X=s[i].x;Y=s[i].y; for (int j=1;j<=k;j++){ if (X+j<n&&a[X+j][Y]<s[i].v&&!use[X+j][Y]){ maxn=max(maxn,dp[X+j][Y]); } if (Y-j>=0&&a[X][Y-j]<s[i].v&&!use[X][Y-j]){ maxn=max(maxn,dp[X][Y-j]); } if (X-j>=0&&a[X-j][Y]<s[i].v&&!use[X-j][Y]){ maxn=max(maxn,dp[X-j][Y]); } if (Y+j<n&&a[X][Y+j]<s[i].v&&!use[X][Y+j]){ maxn=max(maxn,dp[X][Y+j]); } }//cout<<maxn<<endl; if (maxn==-1) use[X][Y]=1; dp[X][Y]=maxn+s[i].v; ans=max(ans,dp[X][Y]); // cout<<ans<<endl; //cout<<s[i].x<<" "<<s[i].y<<" "<<s[i].v<<" "; } cout<<ans<<endl; } return 0; }
poj_1836_Alignment
http://poj.org/problem?id=1836
队长检查士兵,n个士兵们排队高矮不齐,队长希望提出几个士兵,使得队伍里的每个士兵左边或右边的士兵都比他矮。
从左往右求LIS dp0[i]表示已i为结尾的最长子序列长度。
从右往左求LIS dp1[j]表示已j为结尾的最长子序列长度。
然后枚举i和j求出最小的n-dp0[i]-dp1[j];注意dp0[n-1]和dp1[0]两种特殊情况。
<pre name="code" class="cpp">#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #ifndef INF #define INF 1000000000 #endif int n; void solve (double a[],int dp[]){ dp[0]=0; for (int i=0;i<n;i++){ dp[i]=1; for (int j=0;j<i;j++){ if (a[i]>a[j]){ dp[i]=max(dp[i],dp[j]+1); } } } } void swapd (int dp[0]){ for (int i=0;i<n/2;i++){ swap(dp[i],dp[n-1-i]); } } int main(){ double a[1010],b[1010]; int dp0[1010],dp1[1010]; memset(dp0,0,sizeof(dp0)); cin>>n; for (int i=0;i<n;i++){ cin>>a[i]; b[n-1-i]=a[i]; } solve(a,dp0); solve(b,dp1); swapd(dp1); /*for (int i=0;i<n;i++){ printf ("%d ",dp0[i]); }printf ("\n"); for (int i=0;i<n;i++){ printf ("%d ",dp1[i]); }printf ("\n"); cout<<endl;*/ int ans=min(n-dp0[n-1],n-dp1[0]); for (int i=0;i<n-1;i++){ for (int j=i+1;j<n;j++){ ans=min(ans,n-dp0[i]-dp1[j]); } } cout<<ans<<endl; return 0; }
dp总是水我这样好吗==