动态规划

 最长公共子序列:

模版:
int dp[MAX][MAX],n; 
int maxlen(int x[],int y[]){
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
if(x[i]==y[j]){
dp[i][j]=max(dp[i-1][j-1]+1,dp[i][j]);
}
}
}
return dp[n][n];
}

uva 111 - History Grading   

View Code

uva 10405 - Longest Common Subsequence

View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6 #define MAX 1100
7 #define INF 2000000000
8 int dp[MAX][MAX],n;
9
10 int maxlen(char *x,char *y){
11 memset(dp,0,sizeof(dp));
12 int lenx=strlen(x),leny=strlen(y);
13 for(int i=lenx;i>0;i--) x[i]=x[i-1]; x[lenx+1]='\0';
14 for(int i=leny;i>0;i--) y[i]=y[i-1]; y[leny+1]='\0';
15 for(int i=1;i<=lenx;i++){
16 for(int j=1;j<=leny;j++){
17 dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
18 if(x[i]==y[j]){
19 dp[i][j]=max(dp[i-1][j-1]+1,dp[i][j]);
20 }
21 }
22 }
23 return dp[lenx][leny];
24 }
25 char a[MAX],b[MAX];
26 int main(){
27 while(gets(a)!=0){
28 gets(b);
29 printf("%d\n",maxlen(a,b));
30 }
31 }

uva 531 - Compromise

注意PE,PE了无数把View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<map>
5 #include<cstring>
6 #include<string>
7 #include<cstdlib>
8 #include<algorithm>
9 using namespace std;
10 #define nMAX 110
11 #define mMAX 51000
12 #define INF 2000000000
13
14 int a[nMAX],b[nMAX],dp[nMAX][nMAX];
15 map<string,int> mpp; map<int,string> rmpp;
16 int cnt,cnta,cntb;
17 struct node{
18 int x,y;
19 }pre[nMAX][nMAX];
20
21 int input(){
22 string s;
23 if(cin>>s){
24 mpp.clear(); rmpp.clear();
25 cnt=1,cnta=1,cntb=1;
26 if(!mpp[s]) {
27 rmpp[cnt]=s; mpp[s]=cnt++;
28 }
29 a[cnta++]=mpp[s];
30 int flag=1; if(s=="#") flag=0;
31 while(flag&&cin>>s&&s!="#"){
32 if(!mpp[s]) {
33 rmpp[cnt]=s; mpp[s]=cnt++;
34 }
35 a[cnta++]=mpp[s];
36 }
37 while(cin>>s&&s!="#"){
38 if(!mpp[s]) {
39 mpp[s]=cnt++; rmpp[cnt]=s;
40 }
41 b[cntb++]=mpp[s];
42 }
43 return 1;
44 }else return 0;
45
46 }
47 int maxlen(int *x,int *y){
48 memset(dp,0,sizeof(dp));
49 memset(pre,-1,sizeof(pre));
50 for(int i=1;i<cnta;i++){
51 for(int j=1;j<cntb;j++){
52 if(dp[i-1][j]>dp[i][j-1]){
53 dp[i][j]=dp[i-1][j];
54 pre[i][j].x=i-1; pre[i][j].y=j;
55 }else{
56 dp[i][j]=dp[i][j-1];
57 pre[i][j].x=i; pre[i][j].y=j-1;
58 }
59 if(x[i]==y[j]&&dp[i-1][j-1]+1>dp[i][j]){
60 dp[i][j]=dp[i-1][j-1]+1;
61 pre[i][j].x=i-1; pre[i][j].y=j-1;
62 }
63 }
64 }
65 return dp[cnta-1][cntb-1];
66 }
67 int ans[nMAX],cntans;
68 void print(int x,int y){
69 if(x==-1||x==0||y==0||y==-1) return ;
70 print(pre[x][y].x,pre[x][y].y);
71 if(rmpp[a[x]]==rmpp[b[y]]) ans[cntans++]=a[x];
72 }
73 int main(){
74 while(input()){
75 maxlen(a,b);
76 cntans=0;
77 print(cnta-1,cntb-1);
78 for(int i=0;i<cntans;i++){
79 if(i!=cntans-1) cout<<rmpp[ans[i]]<<" ";
80 else cout<<rmpp[ans[i]]<<endl;
81 }
82 }
83 }



最长上升子序列:

nlogn模版 
dp[0```n]代表dp[i]在a[i]处所对应的最长上升序列
int c[MAX],len;
int find(int L,int R,int x)
{
if(L==R) return L;
int mid=(L+R)>>1;
if(c[mid]<x) return find(mid+1,len,x);
else return find(L,mid,x);
}
int lis(int *a,int *dp,int n){
int j; len=0; c[0]=-INF;
for(int i=0;i<n;i++)
{
if(a[i]>c[len]) j=++len;
else j=find(1,len,a[i]);
c[j]=a[i];
dp[i]=j;
}
return len;
}

uva 103 - Stacking Boxes   

View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6 #define MAX 300
7 #define INF 2000000000
8 int m,n;
9 struct node{
10 int num[MAX];
11 int id;
12 }ar[MAX];
13 bool cmp(const node x,const node y){
14 for(int i=0;i<m;i++){
15 if(x.num[i]>y.num[i]) return true;
16 else if(x.num[i]<y.num[i]) return false;
17 }
18 return false;
19 }
20 int dp[MAX],pre[MAX];
21 bool compare(int *x,int *y){
22 for(int i=0;i<m;i++){
23 if(x[i]>=y[i]) return false;
24 }
25 return true;
26 }
27 int main(){
28 while(scanf("%d%d",&n,&m)!=EOF){
29 memset(dp,0,sizeof(dp));
30 for(int i=0;i<n;i++){
31 ar[i].id=i;
32 for(int j=0;j<m;j++){
33 scanf("%d",&ar[i].num[j]);
34 }
35 }
36 for(int i=0;i<n;i++){
37 sort(ar[i].num,ar[i].num+m);
38 }
39 sort(ar,ar+n,cmp);
40 memset(pre,-1,sizeof(pre));
41 int maxn=-INF,id=-1;
42 dp[0]=1;
43 for(int i=0;i<n;i++){
44 for(int j=0;j<i;j++){
45 if(compare(ar[i].num,ar[j].num)&&dp[i]<dp[j]+1){
46 pre[i]=j; dp[i]=dp[j]+1;
47 }
48 }
49 if(maxn<dp[i]) {
50 maxn=dp[i];
51 id=i;
52 }
53 }
54 if(id!=-1) printf("%d\n",dp[id]);
55 for(int i=id;i!=-1;i=pre[i]){
56 if(pre[i]!=-1)printf("%d ",ar[i].id+1);
57 else printf("%d\n",ar[i].id+1);
58 }
59 }
60 }

uva 10131 - Is Bigger Smarter?

View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6 #define nMAX 1100
7 #define INF 2000000000
8 int dp[nMAX],pre[nMAX];
9 struct node{
10 int w,s,id;
11 }ar[nMAX];
12 int ans[nMAX];
13 bool cmp(node a,node b){
14 if(a.w<b.w) return true;
15 else if(a.w>b.w) return false;
16 if(a.s>b.s) return true;
17 else return false;
18 }
19 int main(){
20 int n=0;
21 while(scanf("%d%d",&ar[n].w,&ar[n].s)!=EOF) {
22 ar[n].id=n;
23 n++;
24 }
25 ar[n].id=n; n++;
26 sort(ar,ar+n,cmp);
27 int max_=-INF,num=-1;
28 memset(pre,-1,sizeof(pre));
29 for(int i=0;i<n;i++) dp[i]=1;
30 for(int i=0;i<n;i++){
31 for(int j=i-1;j>=0;j--){
32 if(ar[i].w>ar[j].w&&ar[i].s<ar[j].s&&dp[i]<dp[j]+1){
33 dp[i]=dp[j]+1;
34 pre[i]=j;
35 }
36 }
37 if(dp[i]>max_){
38 max_=dp[i];
39 num=i;
40 }
41 }
42 if(num!=-1)printf("%d\n",dp[num]);
43 else printf("0\n");
44 int cntans=0;
45 for(int i=num;i!=-1;i=pre[i]){
46 ans[cntans++]=ar[i].id+1;
47 }
48 for(int i=cntans-1;i>=0;i--) printf("%d\n",ans[i]);
49 }

 uva 10192 - Vacation

View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6 #define nMAX 1100
7 #define INF 2000000000
8 int dp[nMAX][nMAX],n,m;
9 int maxlen(char x[],char y[]){
10 memset(dp,0,sizeof(dp));
11 n=strlen(x),m=strlen(y);
12 for(int i=n;i>0;i--) x[i]=x[i-1]; x[n+1]='\0';
13 for(int i=m;i>0;i--) y[i]=y[i-1]; y[m+1]='\0';
14 for(int i=1;i<=n;i++){
15 for(int j=1;j<=m;j++){
16 dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
17 if(x[i]==y[j]){
18 dp[i][j]=max(dp[i-1][j-1]+1,dp[i][j]);
19 }
20 }
21 }
22 return dp[n][m];
23 }
24 char a[nMAX],b[nMAX];
25 int main(){
26 int T=1;
27 while(gets(a)){
28 if(a[0]=='#') return 0;
29 gets(b);
30 printf("Case #%d: you can visit at most %d cities.\n",T++,maxlen(a,b));
31 }
32 }

uva 437 - The Tower of Babylon

View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<cstdlib>
6 #include<algorithm>
7 using namespace std;
8 const int MAX=100000;
9 struct node{
10 int x,y,z;
11 }ar[MAX];
12 bool cmp(node a,node b){
13 if(a.x>b.x) return true;
14 else if(a.x<b.x) return false;
15 if(a.y>b.y) return true;
16 return false;
17 }
18 int dp[MAX];
19 int main(){
20 int n,T=1;
21 while(scanf("%d",&n)&&n){
22 for(int i=0;i<n;i++){
23 int a,b,c;
24 scanf("%d%d%d",&a,&b,&c);
25 ar[6*i+0].x=a;
26 ar[6*i+0].y=b;
27 ar[6*i+0].z=c;
28
29 ar[6*i+1].x=a;
30 ar[6*i+1].y=c;
31 ar[6*i+1].z=b;
32
33 ar[6*i+2].x=b;
34 ar[6*i+2].y=a;
35 ar[6*i+2].z=c;
36
37 ar[6*i+3].x=b;
38 ar[6*i+3].y=c;
39 ar[6*i+3].z=a;
40
41 ar[6*i+4].x=c;
42 ar[6*i+4].y=a;
43 ar[6*i+4].z=b;
44
45 ar[6*i+5].x=c;
46 ar[6*i+5].y=b;
47 ar[6*i+5].z=a;
48 }
49 n=6*n;
50 sort(ar,ar+n,cmp);
51 memset(dp,0,sizeof(dp));
52 int max_=0;
53 for(int i=0;i<n;i++){
54 dp[i]=ar[i].z;
55 for(int j=0;j<i;j++){
56 if(ar[i].x<ar[j].x&&ar[i].y<ar[j].y)
57 dp[i]=max(dp[i],dp[j]+ar[i].z);
58 }
59 max_=max(max_,dp[i]);
60 }
61 printf("Case %d: maximum height = %d\n",T++,max_);
62 }
63 }

uva 10534 - Wavio Sequence

nlogn优化 View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<cstdlib>
6 #include<algorithm>
7 using namespace std;
8 const int MAX=11000;
9 const int INF=100000000;
10 int ar[MAX],ra[MAX];
11 int dp1[MAX],dp2[MAX];
12 int c[MAX],len;
13 int find(int L,int R,int x)
14 {
15 if(L==R) return L;
16 int mid=(L+R)>>1;
17 if(c[mid]<x) return find(mid+1,len,x);
18 else return find(L,mid,x);
19 }
20 int lis(int *a,int *dp,int n){
21 int j; len=0; c[0]=-INF;
22 for(int i=0;i<n;i++)
23 {
24 if(a[i]>c[len]) j=++len;
25 else j=find(1,len,a[i]);
26 c[j]=a[i];
27 dp[i]=j;
28 }
29 return len;
30 }
31 int main(){
32 int n;
33 while(scanf("%d",&n)!=EOF){
34 memset(dp1,0,sizeof(dp1));
35 memset(dp2,0,sizeof(dp2));
36 for(int i=0;i<n;i++) {
37 scanf("%d",&ar[i]);
38 ra[n-i-1]=ar[i];
39 }
40 lis(ar,dp1,n);
41 lis(ra,dp2,n);
42 int ans=-1;
43 for(int i=0;i<n;i++){
44 ans=max(ans,2*min(dp1[i],dp2[n-i-1])-1);
45 }
46 printf("%d\n",ans);
47 }
48 }

 

背包 

uva 674 - Coin Change

多重背包 View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6 #define MAX 11000
7 #define INF 2000000000
8 int dp[MAX],n;
9 int ar[10];
10 int main(){
11 ar[0]=50;ar[1]=25;ar[2]=10;ar[3]=5;ar[4]=1;
12 while(scanf("%d",&n)!=EOF){
13 memset(dp,0,sizeof(dp));
14 dp[0]=1;
15 for(int i=0;i<5;i++){
16 for(int j=0;j<=n;j++){
17 if(j-ar[i]>=0){
18 dp[j]+=dp[j-ar[i]];
19 }
20 }
21 }
22 printf("%d\n",dp[n]);
23 }
24 }

uva 147 - Dollars

完全背包 注意四舍五入和输出格式 
View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<cstring>
5 #include<algorithm>
6 using namespace std;
7 #define nMAX 50000
8 #define INF 2000000000
9 int ar[20];
10 long long dp[nMAX];
11 int main(){
12 ar[0]=10000,ar[1]=5000,ar[2]=2000,ar[3]=1000,ar[4]=500;
13 ar[5]=200,ar[6]=100,ar[7]=50,ar[8]=20,ar[9]=10,ar[10]=5;
14 double num;
15 while(scanf("%lf",&num)){
16 int sum;
17 if(fabs(num) < 1e-9) break;
18 sum = floor(num * 100 + 0.5) ;
19 memset(dp,0,sizeof(dp));
20 dp[0]=1;
21 for(int i=0;i<11;i++){
22 for(int j=0;j<=sum;j++){
23 if(j-ar[i]>=0){
24 dp[j]+=dp[j-ar[i]];
25 }
26 }
27 }
28 printf("%6.2f%17lld\n",num,dp[sum]);
29 }
30 }

uva 357-Let Me Count The Ways

 完全背包View Code

uva 562 - Dividing coins

0 1背包 View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<cstring>
5 #include<cstdlib>
6 #include<algorithm>
7 using namespace std;
8 #define nMAX 51000
9 #define INF 2000000000
10 int ar[110];
11 bool dp[nMAX];
12 int main(){
13 int n,T,sum;
14 scanf("%d",&T);
15 while(T--){
16 scanf("%d",&n);
17 sum=0;
18 for(int i=0;i<n;i++) scanf("%d",&ar[i]),sum+=ar[i];
19 memset(dp,0,sizeof(dp));
20 dp[0]=1;
21 for(int i=0;i<n;i++)
22 for(int j=sum/2;j>0;j--)
23 if(j-ar[i]>=0&&dp[j-ar[i]])
24 dp[j]=true;
25 int num=0;
26 for(int i=sum/2;i!=-1;i--) {
27 if(dp[i]) {num=i;break;}
28 }
29 printf("%d\n",abs(num-(sum-num)));
30 }
31 }

uva 624 - CD

0 1背包 View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<cstring>
5 #include<cstdlib>
6 #include<algorithm>
7 using namespace std;
8 #define nMAX 100
9 #define mMAX 11000
10 #define INF 2000000000
11 int ar[nMAX],pre[mMAX][2];
12 bool dp[mMAX];
13 void print(int id){
14 if(id==-1||id==0) return ;
15 print(pre[id][1]);
16 printf("%d ",ar[pre[id][0]]);
17 }
18 int main(){
19 int n,m;
20 while(scanf("%d%d",&m,&n)!=EOF){
21 for(int i=0;i<n;i++) scanf("%d",&ar[i]);
22 memset(dp,0,sizeof(dp)); dp[0]=1;
23 memset(pre,-1,sizeof(pre));
24 for(int i=0;i<n;i++){
25 for(int j=m;j>0;j--){
26 if(j-ar[i]>=0&&dp[j-ar[i]]&&!dp[j]){
27 dp[j]=dp[j-ar[i]];
28 pre[j][0]=i;
29 pre[j][1]=j-ar[i];
30 }
31 }
32 }
33 int id=0;
34 for(int i=m;i>0;i--){
35 if(dp[i]){
36 id=i; break;
37 }
38 }
39 print(id);
40 printf("sum:%d\n",id);
41 }
42 }

uva 10130 - SuperSale

0 1背包 注意每个人对每种物品都可取一次
View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<cstring>
5 #include<cstdlib>
6 #include<algorithm>
7 using namespace std;
8 #define nMAX 1100
9 #define mMAX 51000
10 #define INF 2000000000
11 int ar[nMAX][2],dp[mMAX],p[nMAX];
12 int main(){
13 int T,n,m;
14 scanf("%d",&T);
15 while(T--){
16 scanf("%d",&n);
17 for(int i=0;i<n;i++) scanf("%d%d",&ar[i][0],&ar[i][1]);
18 scanf("%d",&m);
19 int max_=-INF;
20 for(int i=0;i<m;i++) {
21 scanf("%d",&p[i]);
22 max_=max(p[i],max_);
23 }
24 memset(dp,0,sizeof(dp));
25 for(int i=0;i<n;i++){
26 for(int j=max_;j>0;j--){
27 if(j-ar[i][1]>=0){
28 dp[j]=max(dp[j-ar[i][1]]+ar[i][0],dp[j]);
29 }
30 }
31 }
32 int ans=0;
33 for(int i=0;i<m;i++){
34 ans+=dp[p[i]];
35 }
36 printf("%d\n",ans);
37 }return 0;
38 }

 uva 10465 - Homer Simpson

0 1背包 解方程View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<map>
5 #include<cstring>
6 #include<string>
7 #include<cstdlib>
8 #include<algorithm>
9 using namespace std;
10 #define nMAX 11000
11 #define mMAX 51000
12 #define INF 2000000000
13 int a[10],dp[nMAX];
14 int main(){
15 int t;
16 while(scanf("%d%d%d",&a[0],&a[1],&t)!=EOF){
17 memset(dp,0,sizeof(dp));
18 for(int i=0;i<2;i++){
19 for(int j=0;j<=t;j++){
20 if(((j-a[i]>0&&dp[j-a[i]])||j-a[i]==0)&&dp[j-a[i]]+1>dp[j]){
21 dp[j]=dp[j-a[i]]+1;
22 }
23 }
24 }
25 if(dp[t]) printf("%d\n",dp[t]);
26 else{
27 int ans=0;
28 for(int i=t;i;i--)
29 if(dp[i]) break;
30 else ans++;
31 printf("%d %d\n",dp[t-ans],ans);
32 }
33 }
34 }

10404 - Bachet's Game

背包应用 博弈View Code
 1 int ar[MAX];
2 int dp[MAX];
3 int main(){
4 int n,m;
5 while(scanf("%d%d",&n,&m)!=EOF){
6 memset(dp,0,sizeof(dp));
7 int cnt=0;
8 for(int i=0;i<m;i++){
9 int x;
10 scanf("%d",&x);
11 if(x<=n&&x>0) ar[cnt++]=x;
12 }
13 for(int i=0;i<=n;i++){
14 for(int j=0;j<cnt;j++){
15 if(i-ar[j]>=0&&dp[i-ar[j]]==false){
16 dp[i]=true; break;
17 }
18 }
19 }
20 if(dp[n]) printf("Stan wins\n");
21 else printf("Ollie wins\n");
22 }
23 }



区间动态规划:

10003 - Cutting Sticks

View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6 #define MAX 110
7 #define INF 2000000000
8 int dp[MAX][MAX],n,len;
9 int ar[MAX];
10 int f(int a,int b){
11 if(a+1==b) return dp[a][b]=0;
12 if(dp[a][b]!=-1) return dp[a][b];
13 for(int i=a+1;i<b;i++){
14 int x=f(a,i),y=f(i,b);
15 if(dp[a][b]!=-1) dp[a][b]=min(x+y+ar[b]-ar[a],dp[a][b]);
16 else dp[a][b]=x+y+ar[b]-ar[a];
17 }
18 return dp[a][b];
19 }
20 int main(){
21 while(scanf("%d",&len)&&len){
22 memset(dp,-1,sizeof(dp));
23 scanf("%d",&n);
24 ar[0]=0;
25 for(int i=1;i<=n;i++) scanf("%d",&ar[i]);
26 ar[++n]=len; sort(ar,ar+n+1);
27 printf("The minimum cutting is %d.\n",f(0,n));
28 }
29 }

uva 348 - Optimal Array Multiplication Sequence

可用四边形不等式优化
View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<cstring>
5 #include<cstdlib>
6 #include<algorithm>
7 using namespace std;
8 #define nMAX 100
9 #define INF 2000000000
10 struct A{
11 int x,y,sum;
12 int mid;
13 }dp[nMAX][nMAX];
14 struct B{
15 int x,y;
16 }ar[nMAX];
17 void print(int a,int b){
18 if(a==b){ printf("A%d",a+1); return ;}
19 printf("(");
20 print(a,dp[a][b].mid);
21 printf(" x ");
22 print(dp[a][b].mid+1,b);
23 printf(")");
24 }
25 int main(){
26 int n,T=1;
27 while(scanf("%d",&n)&&n){
28 for(int i=0;i<n;i++)
29 scanf("%d%d",&ar[i].x,&ar[i].y);
30 memset(dp,0,sizeof(dp));
31 for(int i=0;i<n;i++)
32 dp[i][i].x=ar[i].x,dp[i][i].y=ar[i].y,dp[i][i].sum=1;
33 for(int i=1;i<n;i++){
34 for(int j=0;j+i<n;j++){
35 int max_=INF,id;
36 for(int k=j;k<j+i;k++){
37 if(max_>dp[j][k].x*dp[k+1][j+i].y*dp[j][k].y+dp[j][k].sum+dp[k+1][j+i].sum){
38 max_=dp[j][k].x*dp[k+1][j+i].y*dp[j][k].y+dp[j][k].sum+dp[k+1][j+i].sum;
39 id=k;
40 }
41 dp[j][j+i].sum=max_;
42 dp[j][j+i].x=dp[j][k].x;
43 dp[j][j+i].y=dp[k+1][j+i].y;
44 dp[j][j+i].mid=id;
45 }
46 }
47 }
48 printf("Case %d: ",T++);
49 print(0,n-1);
50 printf("\n");
51 }
52 }


简单动态规划

uva 116 - Unidirectional TSP (注意输出要按照字典序输出)

View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6 #define nMAX 30
7 #define mMAX 510
8 #define INF 2000000000
9 int dp[nMAX][mMAX],n,m,pre[nMAX][mMAX];
10 int mpp[nMAX][mMAX];
11 int a[mMAX],b[mMAX];
12 bool compare(int x,int y,int col){
13 int cnt=col;
14 for(int k=col,i=x;i!=-1;){
15 a[cnt--]=i;
16 i=pre[i][k],k--;
17 }
18 cnt=col;
19 for(int k=col,i=y;i!=-1;){
20 b[cnt--]=i;
21 i=pre[i][k],k--;
22 }
23 for(int i=1;i<=col;i++){
24 if(a[i]>b[i]) return false;
25 else if(a[i]<b[i]) return true;
26 }
27 return false;
28 }
29 int main(){
30 while(scanf("%d%d",&m,&n)!=EOF){
31 memset(mpp,0,sizeof(mpp));
32 for(int i=1;i<=m;i++)
33 for(int j=1;j<=n;j++)
34 scanf("%d",&mpp[i][j]);
35
36 memset(pre,-1,sizeof(pre));
37 memset(dp,0,sizeof(dp));
38 for(int i=1;i<=m;i++) dp[i][1]=mpp[i][1];
39 for(int i=2;i<=n;i++){
40 for(int j=1;j<=m;j++){
41 int id=j,x;
42 x=j-1; if(x<1) x+=m;
43 if(dp[x][i-1]<dp[id][i-1]||(dp[x][i-1]==dp[id][i-1]&&compare(x,id,i-1))) id=x;
44
45 x=j+1;if(x>m) x-=m;
46 if(dp[x][i-1]<dp[id][i-1]||(dp[x][i-1]==dp[id][i-1]&&compare(x,id,i-1))) id=x;
47
48 pre[j][i]=id; dp[j][i]=mpp[j][i]+dp[id][i-1];
49 }
50 }
51 int min_num=INF,num;
52 for(int j=1;j<=m;j++){
53 if(dp[j][n]<min_num){
54 min_num=dp[j][n];
55 num=j;
56 }
57 }
58 for(int i=1;i<=m;i++)
59 if(dp[i][n]==min_num&&!compare(num,i,n)) num=i;
60 compare(num,num,n);
61 for(int i=1;i<=n;i++)
62 if(i!=n) printf("%d ",a[i]);
63 else printf("%d\n",a[i]);
64 printf("%d\n",dp[num][n]);
65 }
66 }

 

 

状态压缩 

 

皇后问题

SGU - 223

写的很暴力 
View Code
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include <iomanip>
#include <bitset>
using namespace std;
const int MAX=(1<<10);
const int INF=100000000;
bool vis[MAX][MAX];
long long dp[11][MAX][105];
bool ok(int x,int y){
if(((x<<1)&y)
||(x&(y<<1))
||(x&y)
||((x<<1)&x)
||((y<<1)&y))
return false;
return true;
}
int op(int x){
int ans=0;
while(x){
if(x&1) ans++;
x>>=1;
}
return ans;
}
int main(){
int n,m;
while(cin>>n>>m){
memset(vis,0,sizeof(vis));
memset(dp,0,sizeof(dp));
for(int i=0;i<(1<<n);i++)
for(int j=0;j<(1<<n);j++)
vis[i][j]=ok(i,j);
for(int i=0;i<(1<<n);i++)
if(vis[i][0]) dp[0][i][op(i)]=1;
for(int i=1;i<n;i++){
for(int j=0;j<(1<<n);j++){
for(int rj=op(j);rj<=m&&rj<=(i+1)*n/2;rj++){
for(int k=0;k<(1<<n);k++){
if(vis[j][k]){
dp[i][j][rj]+=dp[i-1][k][rj-op(j)];
}
}
}
}
}
long long sum=0;
for(int i=0;i<(1<<n);i++)
sum+=dp[n-1][i][m];
cout<<sum<<endl;
}
}

优化参考一下  http://www.cnblogs.com/dementrock/archive/2010/02/16/1668779.html

View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<vector>
4 #include<cstring>
5 #include<cmath>
6 #include<queue>
7 #include<cstdlib>
8 #include<algorithm>
9 #include <iomanip>
10 #include <bitset>
11 using namespace std;
12 int s[145],c[145],m,n,k;
13 long long f[11][145][101];
14 void dfs(int l, int now, int total)
15 {
16 if(l==n)
17 {
18 s[++m]=now;
19 c[m]=total;
20 return;
21 }
22 dfs(l+1,now<<1,total);
23 if(!(now&1))
24 dfs(l+1,(now<<1)|1,total+1);
25 }
26 void dp(int l, int t, int k)
27 {
28 f[l][t][k]=0;
29 for(int i=1;i<=m;++i)
30 if(k>=c[t]&&!(s[i]&s[t])&&!((s[i]>>1)&s[t])&&!((s[i]<<1)&s[t]))
31 {
32 if(f[l-1][i][k-c[t]]==-1)
33 dp(l-1,i,k-c[t]);
34 f[l][t][k]+=f[l-1][i][k-c[t]];
35 }
36 }
37 int main()
38 {
39 long long ans=0;
40 scanf("%d%d",&n,&k);
41 memset(f,0xff,sizeof(f));
42 dfs(0,0,0);
43 memset(f[0],0,sizeof(f[0]));
44 f[0][1][0]=1;
45 for(int i=1;i<=m;++i)
46 {
47 if(f[n][i][k]==-1)
48 dp(n,i,k);
49 ans+=f[n][i][k];
50 }
51 printf("%I64d\n",ans);
52 return 0;
53 }

 

字符串处理

uva 10651 - Pebble Solitaire

View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<vector>
4 #include<cstring>
5 #include<cmath>
6 #include<queue>
7 #include<cstdlib>
8 #include<algorithm>
9 #include <iomanip>
10 #include <bitset>
11 using namespace std;
12 const int MAX=(1<<15);
13 const int INF=100000000;
14 int len;
15 int dp[MAX];
16 int op(int x){
17 int ans=0;
18 while(x){
19 if(x&1) ans++;
20 x>>=1;
21 }
22 return ans;
23 }
24 int dfs(int x){
25 if(dp[x]!=-1) return dp[x];
26 for(int i=0;i<=len;i++){
27 if(i+2<=len
28 &&((1<<i)&x)
29 &&(1<<(i+1)&x)
30 &&!((1<<(i+2))&x)){
31 int temp=x;
32 temp|=( 1<<(i+2) );
33 temp^=( 1<<(i+1) );
34 temp^=( 1<<i );
35 //cout<<bitset<12>(temp)<<endl;
36 if(dp[x]!=-1)dp[x]=min(dfs(temp),dp[x]);
37 else dp[x]=dfs(temp);
38
39 }
40 if(i-2>=0
41 &&((1<<i)&x)
42 &&(1<<(i-1)&x)
43 &&!((1<<(i-2))&x)){
44 int temp=x;
45 temp|=( 1<<(i-2) );
46 temp^=( 1<<(i-1) );
47 temp^=( 1<<i );
48 //cout<<bitset<12>(temp)<<endl;
49 if(dp[x]!=-1)dp[x]=min(dfs(temp),dp[x]);
50 else dp[x]=dfs(temp);
51
52 }
53 }
54 if(dp[x]==-1) return op(x);
55 else return dp[x];
56 }
57 int main(){
58 int T,n; char str[20];
59 scanf("%d",&T);
60 while(T--){
61 scanf("%s",str); n=0;
62 len=strlen(str)-1;
63 memset(dp,-1,sizeof(dp));
64 for(int i=0;i<strlen(str);i++){
65 if(str[i]=='o') n+=(1<<i);
66 }
67 //cout<<bitset<12>(n)<<endl;
68 printf("%d\n",dfs(n));
69 }
70 }

ZOJ  2745

http://www.cnblogs.com/louisnit/archive/2012/04/26/2471668.html

树状dp

hdu 2196 http://www.cnblogs.com/louisnit/archive/2012/04/24/2468768.html

hdu 4169 http://www.cnblogs.com/louisnit/archive/2012/03/27/2420284.html

posted @ 2012-03-04 13:31  HaoHua_Lee  阅读(259)  评论(0编辑  收藏  举报