几道DP题

  联合训练赛中遇到的(以后留给新生做):

1.排列的逆序数

题目描述

{1,2...n}的所有排列中逆序数为k的排列个数。

输入

多组样例,每组样例: n, k ( 1≤n≤100, 0≤k≤n*(n-1)/2)

输出

对于每个样例,输出排列个数,答案模1000000007。

样例输入

2 1

样例输出

1

简单DP,转移方程: f[i][j]为前i个数所有排列中逆序数为j的个数,则f[i][j]=Σ( f[i-1][k] | max(0,j-i+1)<k<=j )。
 1 //STATUS:C++_AC_93MS_1348KB
 2 #include <functional>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <fstream>
 6 #include <sstream>
 7 #include <iomanip>
 8 #include <numeric>
 9 #include <cstring>
10 #include <cassert>
11 #include <cstdio>
12 #include <string>
13 #include <vector>
14 #include <bitset>
15 #include <queue>
16 #include <stack>
17 #include <cmath>
18 #include <ctime>
19 #include <list>
20 #include <set>
21 #include <map>
22 //#include <ext/rope>
23 using namespace std;
24 //define
25 #define pii pair<int,int>
26 #define mem(a,b) memset(a,b,sizeof(a))
27 #define lson l,mid,rt<<1
28 #define rson mid+1,r,rt<<1|1
29 #define PI acos(-1.0)
30 //typedef
31 typedef long long LL;
32 typedef unsigned long long ULL;
33 //const
34 const int N=10010;
35 const int INF=0x3f3f3f3f;
36 const int MOD=1000000007,STA=8000010;
37 const LL LNF=1LL<<60;
38 const double EPS=1e-8;
39 const double OO=1e15;
40 //Daily Use ...
41 inline int sign(double x){return (x>EPS)-(x<-EPS);}
42 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
43 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
44 template<class T> inline T Min(T a,T b){return a<b?a:b;}
45 template<class T> inline T Max(T a,T b){return a>b?a:b;}
46 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
47 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
48 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
49 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
50 //End
51 
52 int f[2][N*2];
53 int n,m;
54 
55 int main()
56 {
57  //   freopen("in.txt","r",stdin);
58     int i,j,k,up,p;
59     while(~scanf("%d%d",&n,&m))
60     {
61         p=1;
62         mem(f,0);
63         f[0][0]=1;
64         for(i=0;i<n;i++){
65             up=Min(m,i*(i-1)/2);
66             for(j=0;j<=up;j++){
67                 for(k=0;k<=i;k++)
68                     f[p][j+k]=(f[p][j+k]+f[!p][j])%MOD;
69             }
70             mem(f[p=!p],0);
71         }
72 
73         printf("%d\n",f[!p][m]);
74     }
75     return 0;
76 }
View Code

 

2.括号匹配

题目描述

给一个字符串s。包含(,),?三种字符,?可以代表变成(或)。求出所有合法匹配个数。

输入

多组样例,每组样例: 一个字符串s,|s|<=1000。

输出

对于每个样例,输出合法匹配个数,答案模1000000007。

样例输入

(??)

样例输出

2

把 ( 和 ) 分别装换为 -1 和 1 ,则就是求前缀和满足>=0和<=n/2的状态数。
设f[i][j]为前i个字符前缀为j的个数,则
1.s[i]==')',f[i][j]=Σ( f[i-1][j-1] | j>1 )
2.s[i]=='(',f[i][j]=Σ( f[i-1][j+1] | j<n/2 )
3.s[i]=='?',f[i][j]=Σ( f[i-1][j-1] | j>1 ) + Σ( f[i-1][j+1] | j<n/2 )
 1 //STATUS:C++_AC_30MS_5188KB
 2 #include <functional>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <fstream>
 6 #include <sstream>
 7 #include <iomanip>
 8 #include <numeric>
 9 #include <cstring>
10 #include <cassert>
11 #include <cstdio>
12 #include <string>
13 #include <vector>
14 #include <bitset>
15 #include <queue>
16 #include <stack>
17 #include <cmath>
18 #include <ctime>
19 #include <list>
20 #include <set>
21 #include <map>
22 //#include <ext/rope>
23 using namespace std;
24 //define
25 #define pii pair<int,int>
26 #define mem(a,b) memset(a,b,sizeof(a))
27 #define lson l,mid,rt<<1
28 #define rson mid+1,r,rt<<1|1
29 #define PI acos(-1.0)
30 //typedef
31 typedef long long LL;
32 typedef unsigned long long ULL;
33 //const
34 const int N=1010;
35 const int INF=0x3f3f3f3f;
36 const int MOD=1000000007,STA=8000010;
37 const LL LNF=1LL<<60;
38 const double EPS=1e-8;
39 const double OO=1e15;
40 //Daily Use ...
41 inline int sign(double x){return (x>EPS)-(x<-EPS);}
42 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
43 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
44 template<class T> inline T Min(T a,T b){return a<b?a:b;}
45 template<class T> inline T Max(T a,T b){return a>b?a:b;}
46 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
47 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
48 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
49 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
50 //End
51 
52 LL f[N][N/2];
53 char s[N];
54 
55 int main()
56 {
57  //   freopen("in.txt","r",stdin);
58     int i,j,len,mid;
59     while(~scanf("%s",s))
60     {
61         len=strlen(s);
62         mid=len>>1;
63         mem(f,0);
64         f[0][0]=1;
65         for(i=0;i<len;i++){
66             for(j=0;j<=mid;j++){
67                 if(!f[i][j])continue;
68                 if((s[i]=='(' || s[i]=='?') && j<mid){
69                     f[i+1][j+1]=(f[i+1][j+1]+f[i][j])%MOD;
70                 }
71                 if((s[i]==')' || s[i]=='?') && j>0){
72                     f[i+1][j-1]=(f[i+1][j-1]+f[i][j])%MOD;
73                 }
74             }
75         }
76         printf("%I64d\n",f[len][0]);
77     }
78     return 0;
79 }
View Code

3.物品选择

题目描述

有若干物品,每个物品有一定价值,物品分为主件和附件,主件可以直接选择,附件在主件被选择后才可以选择,附件没有附件。选出一些物品使价值总和最大。

输入

多组样例,每组样例: 第一行输入n,k。(0≤k≤n≤1000)代表物品数目和可以选择的物品数目。 接下来的n行每行输入v和p(0≤v≤1000, 1≤p≤ n),第i行的v和p分别代表第i个物品的价值,和它所依附的主件的编号,若它所依附的主件是它自己,则它本身是主件。

输出

对于每个样例,输出最大的价值和。

样例输入

3 2
1 1
2 1
3 3

样例输出

4

   有依赖的背包。

  1 //STATUS:C++_AC_31MS_5408KB
  2 #include <functional>
  3 #include <algorithm>
  4 #include <iostream>
  5 #include <fstream>
  6 #include <sstream>
  7 #include <iomanip>
  8 #include <numeric>
  9 #include <cstring>
 10 #include <cassert>
 11 #include <cstdio>
 12 #include <string>
 13 #include <vector>
 14 #include <bitset>
 15 #include <queue>
 16 #include <stack>
 17 #include <cmath>
 18 #include <ctime>
 19 #include <list>
 20 #include <set>
 21 #include <map>
 22 //#include <ext/rope>
 23 using namespace std;
 24 //define
 25 #define pii pair<int,int>
 26 #define mem(a,b) memset(a,b,sizeof(a))
 27 #define lson l,mid,rt<<1
 28 #define rson mid+1,r,rt<<1|1
 29 #define PI acos(-1.0)
 30 //typedef
 31 typedef long long LL;
 32 typedef unsigned long long ULL;
 33 //const
 34 const int N=1010;
 35 const int INF=0x3f3f3f3f;
 36 const int MOD=100000,STA=8000010;
 37 const LL LNF=1LL<<60;
 38 const double EPS=1e-8;
 39 const double OO=1e15;
 40 //Daily Use ...
 41 inline int sign(double x){return (x>EPS)-(x<-EPS);}
 42 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
 43 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
 44 template<class T> inline T Min(T a,T b){return a<b?a:b;}
 45 template<class T> inline T Max(T a,T b){return a>b?a:b;}
 46 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
 47 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
 48 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
 49 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
 50 //End
 51 
 52 int w[N][N],v[N][N],cnt[N],ma[N],num[N][2],f[2][N];
 53 int n,m,k;
 54 
 55 void zo(int w[],int v[],int k)
 56 {
 57     int i,j;
 58     for(i=1;i<k;i++){
 59         for(j=k-1;j>=1;j--)
 60             v[j]=Max(v[j],v[j-1]+w[i]);
 61     }
 62 }
 63 
 64 int main()
 65 {
 66  //   freopen("in.txt","r",stdin);
 67     int i,j,a,b,t,p,q;
 68     while(~scanf("%d%d",&n,&m))
 69     {
 70         k=1;
 71         mem(v,0);
 72         for(i=1;i<=n;i++){
 73             scanf("%d%d",&num[i][0],&num[i][1]);
 74             if(num[i][1]==i){
 75                 w[k][0]=num[i][0];
 76                 cnt[k]=1;
 77                 ma[i]=k++;
 78             }
 79         }
 80         for(i=1;i<=n;i++){
 81             if(num[i][1]!=i){
 82                 t=ma[num[i][1]];
 83                 w[t][cnt[t]++]=num[i][0];
 84             }
 85         }
 86         for(i=1;i<k;i++){
 87             zo(w[i],v[i],cnt[i]);
 88             for(j=0;j<cnt[i];j++)
 89                 v[i][j]+=w[i][0];
 90         }
 91                 /*
 92         for(i=1;i<k;i++){
 93             for(j=0;j<cnt[i];j++)
 94                 printf("%d ",v[i][j]);
 95             putchar('\n');
 96         }
 97         */
 98         mem(f,0);
 99         q=1;
100         for(i=1;i<k;i++){
101             for(j=0;j<cnt[i];j++){
102                 for(p=m;p>=j+1;p--){
103                     f[q][p]=Max(f[q][p],f[!q][p-j-1]+v[i][j]);
104                 }
105             }
106             q=!q;
107             for(j=0;j<=m;j++){
108                 f[q][j]=f[!q][j];
109             }
110             /*
111             for(j=0;j<=m;j++)
112                 printf(" %d",f[q][j]);
113             putchar('\n');*/
114         }
115         int ans=-INF;
116         for(i=0;i<=n && i<=m;i++)ans=Max(ans,f[q][i]);
117         printf("%d\n",ans);
118     }
119     return 0;
120 }
View Code

 

4.卡片重组

题目描述

小板有很多卡片,每个卡片上都有一个唯一的数字。某天,小板的哥哥--大板想和小板玩一个游戏。大板将卡片排列在桌上,形成一排,然后要求小板将其分成若干组,但是不能调换卡片的顺序。每组卡片上的数字和乘以卡片数量和就为这组卡片的分数,将每组卡片的分数相加得到总分。大板要求小板得到最多的分数并且每组卡片的上的数字必须是单调的,不然就不带他去公园玩。小板思索很久无法得到结果,所以向你求助。请你帮助小板得到最大的分数。

输入

多组样例,每组样例有一行非负整数。第一个为卡片个数n,n<=1000,接下来为n个卡片数字,每个数字不超过100。

输出

对于每组样例,输出最大的分数。

样例输入

4 2 4 8 3
4 2 3 2 1

样例输出

45
20

  一维DP,f[i]为前i个卡片的最优解,则f[i]={ f[j] + (sum[i]-sum[j-1])*(i-j+1) | j为j-i的数满足单调性 }

 1 //STATUS:C++_AC_15MS_1204KB
 2 #include <functional>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <fstream>
 6 #include <sstream>
 7 #include <iomanip>
 8 #include <numeric>
 9 #include <cstring>
10 #include <cassert>
11 #include <cstdio>
12 #include <string>
13 #include <vector>
14 #include <bitset>
15 #include <queue>
16 #include <stack>
17 #include <cmath>
18 #include <ctime>
19 #include <list>
20 #include <set>
21 #include <map>
22 //#include <ext/rope>
23 using namespace std;
24 //define
25 #define pii pair<int,int>
26 #define mem(a,b) memset(a,b,sizeof(a))
27 #define lson l,mid,rt<<1
28 #define rson mid+1,r,rt<<1|1
29 #define PI acos(-1.0)
30 //typedef
31 typedef long long LL;
32 typedef unsigned long long ULL;
33 //const
34 const int N=1010;
35 const int INF=0x3f3f3f3f;
36 const int MOD=100000,STA=8000010;
37 const LL LNF=1LL<<60;
38 const double EPS=1e-8;
39 const double OO=1e15;
40 //Daily Use ...
41 inline int sign(double x){return (x>EPS)-(x<-EPS);}
42 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
43 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
44 template<class T> inline T Min(T a,T b){return a<b?a:b;}
45 template<class T> inline T Max(T a,T b){return a>b?a:b;}
46 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
47 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
48 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
49 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
50 //End
51 
52 int num[N],f[N];
53 int T,n;
54 
55 int si(int a,int b)
56 {
57     if(a>b)return 1;
58     else if(a<b)return -1;
59     return 0;
60 }
61 
62 int main()
63 {
64  //   freopen("in.txt","r",stdin);
65     int i,j,t,k,cnt,s;
66     while(~scanf("%d",&n))
67     {
68         for(i=1;i<=n;i++)
69             scanf("%d",&num[i]);
70         f[1]=num[1];
71         for(i=2;i<=n;i++){
72             f[i]=f[i-1]+num[i];
73             t=si(num[i],num[i-1]);
74             if(!t)continue;
75             cnt=s=0;
76             for(j=i;t==si(num[j],num[j-1]) && j>1;j--){
77                 s+=num[j];
78                 cnt++;
79                 f[i]=Max(f[i],f[j-1]+cnt*s);
80             }
81             cnt++;
82             s+=num[j];
83             f[i]=Max(f[i],f[j-1]+cnt*s);
84         }
85 
86         printf("%d\n",f[n]);
87     }
88     return 0;
89 }
View Code

 


posted @ 2013-05-21 01:39  zhsl  阅读(372)  评论(0编辑  收藏  举报