动态规划实例
//Made by syx //Time 2010年8月15日 10:13:12 // //
小结:DP的基本思想 如果各个子问题不是独立的,不同的子问题的个数只是多项式量级, 如果我们能够保存已经解决的子问题的答案,而在需要的时候再找 出已求得的答案,这样就可以避免大量的重复计算。 由此而来的基本思路是——用一个表记录所有已解决的子 问题的答案,不管该问题以后是否被用到,只要它被计算过,就将 其结果填入表中。
/* //1421 搬寝室
#include <stdio.h> #include <stdlib.h> #define size 2005 #define INIT 2147483646
int cmp(const void *a,const void *b) { return *(int *)a-*(int *)b; }
int Min(int a,int b) { return a<b?a:b; }
int dp[size][1005];
int main() { int n,k,i,j; int val[size] = {0}; dp[0][0] = 0; while (scanf("%d%d",&n,&k)!=EOF) { val[0] = 0; for(i=1;i<=n;i++) scanf("%d",&val[i]); qsort(val+1,n,sizeof(val[0]),cmp); for (i=0;i<=n;i++) { for(j=1;j<=k;j++) dp[i][j] = INIT; } for (i=2;i<=n;i++) { for (j=1;j*2<=i;j++) dp[i][j] = Min(dp[i-2][j-1]+(val[i]-val[i-1])*(val[i]-val[i-1]),dp[i-1][j]); } printf("%d\n",dp[n][k]); } return 0; }
*/
/* //1159 //最长公共子序列问题
#include <iostream> #include <string> using namespace std; int max(int a,int b) { return a >= b ? a : b; }
int a[1000][1000]; int main() { int i , j; //int a[1000][1000];string s1,s2; while(cin>>s1>>s2) { memset(a[0],0,100); for(i=0; i<s1.length(); i++) for(j=0; j<s2.length(); j++) { if(s1[i] == s2[j] ) a[i+1][j+1] = a[i-1+1][j-1+1] + 1; else a[i+1][j+1] = max(a[i-1+1][j+1] , a[i+1][j-1+1]); } cout<<a[s1.length()][s2.length()]<<endl; } return 0; }
*/
/* //1087 //题目就是求在一个有序的序列(从小到大)中求一个和最大的序列,所以 //也是最长序列的扩展 //
#include<iostream> #include <algorithm> using namespace std; int dp[1001]; int num[1001]; int max(int a,int b) { return a>=b?a:b; } int main() { int i,j,n; for(;cin>>n&&n;) { memset(dp,0,sizeof dp); for( i=1;i<=n;i++) { cin>>num[i]; } int maxdp=0; for( i=1;i<=n;i++) for( j=0;j<i;j++) if(num[i]>num[j]) { dp[i]=max(dp[i],dp[j]+num[i]); if(dp[i]>maxdp) maxdp=dp[i]; } cout<<maxdp<<endl; } return 0; }
*/
/* //1160 //题目大意:所有的老鼠都有一个重量(W) 和一个速度(S),要求找出满足以下关系的最长序列 //W[m[1]] < W[m[2]] < ... < W[m[n]] //and //S[m[1]] > S[m[2]] > ... > S[m[n]] //因为是一个二维的关系,处理起来比较麻烦,所以,我们可以先选择对重量进行从小到大排序(也可以选速度),这样,就只需找出以为上的最长上升子序列了。 //状态转移方程 // if (a[j].s>a[i].s && m[j]+1>m[i]) // { // m[i]=m[j]+1; // pre[i]=j; // } //不过题目最后要的输出是最长上升子序列的长度 以及该子序列选取的所有老鼠的编号(从1开始的) //刚开始怎么调试,得出的答案都和Sample Output不是很一样,郁闷了很久
#include <stdio.h> #include <stdlib.h> struct No { int w; int s; int num; }a[1005]; int cmp(const void *c,const void *d) { return *(int *)c-*(int *)d; } int main () { int n=0,i,j,k,max; int m[1005],pre[1005],p[1005]; while (scanf("%d %d",&a[n].w,&a[n].s)!=EOF) { a[n].num=n+1; n++; } qsort(a,n,sizeof(a[0]),cmp); for (i=0;i<n;i++) { m[i]=1;pre[i]=-1; for (j=i-1;j>=0;j--) { if (a[j].s>a[i].s && m[j]+1>m[i]) { m[i]=m[j]+1; pre[i]=j; } } } for (max=0,i=0;i<n;i++) if (m[i]>m[max]) max=i; printf("%d\n",m[max]); k=0; while (pre[max]!=-1) { p[k++]=a[max].num; max=pre[max]; } p[k++]=a[max].num; while (k--) printf ("%d\n",p[k]); return 0; }
*/
/* //1160
#include <stdio.h> #include <iostream> #include <algorithm> #include <stack> #define MAX 1000 using namespace std; struct Mouse { int W; int S; int L; }; Mouse mouse[MAX+10]; int flag[MAX+10]; int f[MAX+10]; bool cmp(const Mouse a,const Mouse b) { if(a.W==b.W) return a.S>b.S; return a.W<b.W; } int main() { int i(1),j,n,w,s; stack<int> stk; f[1]=1; flag[1]=1; while(scanf("%d%d",&w,&s)!=EOF) { mouse[i].W=w; mouse[i].S=s; mouse[i].L=i; i++; } n=i; sort(mouse+1,mouse+n,cmp); for(i=2;i<n;i++) { int temp(0); for(j=1;j<i;j++) { if(mouse[j].W<mouse[i].W&&mouse[j].S>mouse[i].S&&f[j]>temp) { temp=f[j]; flag[i]=j; } f[i]=temp+1; } } int max=-1,maxi; for(i=1;i<n;i++) if(max<f[i]) { max=f[i]; maxi=i; } printf("%d\n",max); for(i=0;i<max;i++) { int j=maxi; stk.push(mouse[j].L); maxi=flag[j]; } while(!stk.empty()) { printf("%d\n",stk.top()); stk.pop(); } return 0; }
*/
/* //最长有序子序列
#include <stdio.h> int main() { int a[9] = {1,4,7,2,5,8,3,6,9}; int f[9] = {1};//保存最长子序列,第一个是1int i,j; for(i=1; i<9; i++) { for(j=i-1; j>=0; j--) { if(a[i]>=a[j]) { f[i] = f[j] + 1; break; } } } for(i=0; i<9; i++) { printf("%d ",f[i]); } return 0; }
*/ /* //数塔问题
#include <iostream> #define maxn 100 using namespace std; int max(int a,int b) { return (a>b?a:b); } int main() { int a[maxn+1][maxn+1],i,j,n; cin >>n; for (i=1;i<=n;i++) for (j=1;j<=i;j++) cin >>a[i][j]; for (i=n-1;i>=1;i--) for (j=1;j<=i;j++) a[i][j]+=max(a[i+1][j],a[i+1][j+1]); cout <<a[1][1]<<endl; return 0; }
*/