多阶段决策问题

每做一次决策就可以得到解的一部分,当所有决策做完以后,完整的解就"浮出水面“。在回溯法中,每次决策对应于给一个结点产生新的子树,而解的生成过程对应一颗解答树,结点的层数就是下一个待填充的位置

UVA116

分析:dp[i][j]记录从(i,j)出发的最小值,本题同时还要求输出字典序最小的解,所以需要计算时记录下一列行号的最小值。

 1 #include "iostream"
 2 #include "cstdio"
 3 #include "cstring"
 4 #include "string"
 5 #include "algorithm"
 6 using namespace std;
 7 const int maxn=100+10;
 8 const int INF=1<<30;
 9 int m,n;
10 int a[maxn][maxn];
11 int dp[maxn][maxn];
12 int Next[maxn][maxn];
13 int main()
14 {
15     //freopen("uva116.txt","r",stdin);
16     //freopen("uva116.out","w",stdout);
17     while(cin>>m>>n)
18     {
19         for(int i=1;i<=m;i++)
20             for(int j=1;j<=n;j++)
21                 cin>>a[i][j];
22         memset(Next,0,sizeof(Next));
23         int ans=INF,f=0;
24         for(int j=n;j>=1;j--){
25             for(int i=1;i<=m;i++){
26                 if(j==n){
27                     dp[i][j]=a[i][j];
28                 }else{
29                     int col[3]={i-1,i,i+1};
30                     if(i==1) col[0]=m;
31                     if(i==m) col[2]=1;
32                     sort(col,col+3);
33                     dp[i][j]=INF;
34                     for(int k=0;k<3;k++){
35                         int v=dp[col[k]][j+1]+a[i][j];
36                         if(v<dp[i][j]){
37                             dp[i][j]=v;
38                             Next[i][j]=col[k];
39                         }
40                     }
41                 }
42                 if(j==1&&ans>dp[i][j]){
43                     ans=dp[i][j];
44                     f=i;
45                 }
46             }
47         }
48         cout<<f;
49         for(int i=Next[f][1],j=2;j<=n;i=Next[i][j],j++)
50             cout<<" "<<i;
51         cout<<endl;
52         cout<<ans<<endl;
53     }
54     return 0;
55 }
View Code

 UVA12563

分析:01背包的变种,注意的就是首先背包不能装满,其次就是在满足歌曲数量尽量多的情况下,再去满足时间尽量长

 1 #include "iostream"
 2 #include "cstdio"
 3 #include "cstring"
 4 #include "string"
 5 using namespace std;
 6 const int maxn=100;
 7 int T,n,w;
 8 int v[maxn];
 9 int vis[maxn*100],dp[maxn*100];
10 int main()
11 {
12     cin>>T;
13     for(int cas=1;cas<=T;cas++)
14     {
15         cin>>n>>w;
16         for(int i=1;i<=n;i++)
17             cin>>v[i];
18         w-=1;
19         memset(vis,0,sizeof(vis));
20         memset(dp,0,sizeof(dp));
21         for(int i=n;i>=1;i--){
22             for(int j=w;j>=0;j--){
23                 if(j>=v[i]){
24                     if(vis[j]<vis[j-v[i]]+1){
25                         vis[j]=vis[j-v[i]]+1;
26                         dp[j]=dp[j-v[i]]+v[i];
27                     }else if(vis[j]==vis[j-v[i]]+1){
28                         dp[j]=max(dp[j],dp[j-v[i]]+v[i]);
29                     }
30                 }
31             }
32         }
33         printf("Case %d: %d %d\n",cas,vis[w]+1,dp[w]+678);
34     }
35 }
View Code

 

posted @ 2017-07-24 15:36  wolf940509  阅读(372)  评论(0编辑  收藏  举报