码迷,mamicode.com
首页 > 其他好文 > 详细

动态规划——背包

时间:2015-09-27 12:32:21      阅读:341      评论:0      收藏:0      [点我收藏+]

标签:

Wikioi 3729 飞扬的小鸟

题目描述 Description

技术分享

输入描述 Input Description

技术分享

输出描述 Output Description

输出文件名为 bird.out。

共两行。

第一行,包含一个整数,如果可以成功完成游戏,则输出 1,否则输出 0。

第二行,包含一个整数,如果第一行为 1,则输出成功完成游戏需要最少点击屏幕数,

否则,输出小鸟最多可以通过多少个管道缝隙。

 

样例输入 Sample Input

技术分享

技术分享

样例输出 Sample Output

【输入输出样例说明】

如下图所示,蓝色直线表示小鸟的飞行轨迹,红色直线表示管道。

技术分享

数据范围及提示 Data Size & Hint

对于 30%的数据:5≤n≤10,5≤m≤10,k=0,保证存在一组最优解使得同一单位时间最多点击屏幕 3 次;

对于 50%的数据:5≤n≤20,5≤m≤10,保证存在一组最优解使得同一单位时间最多点击屏幕 3 次;

对于 70%的数据:5≤n≤1000,5≤m≤100;

对于 100%的数据: 5≤n≤10000, 5≤m≤1000, 0≤k<n, 0<X<m, 0<Y<m, 0<P<n, 0≤L<H  ≤m,L +1<H。

 思路:

难题……,敲了一上午,最高只有70分,最后看了题解才过QAQ

看题就知道是完全背包,但是跟完全背包的一般优化方法又有不同,因为到达一个位置既可以从另外一个位置点击多次,也可以从x-1处点击一次,还要注意如果触顶不会再往上走,还要注意管子上设初值的问题

代码:

①自己敲的70分

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 #include<algorithm>
 6 
 7 using namespace std;
 8 const int maxn = 10005,maxnum = 100000;
 9 struct vain{
10     int high;
11     int low;
12 };
13 
14 int n,m,k,up[maxn],down[maxn],dp[maxn][maxn],vis[maxn];
15 vain upp[maxn];
16 int main(){
17     cin>>n>>m>>k;
18     for(int i = 0;i < n;i++){
19         cin>>up[i]>>down[i];
20         
21     }
22     int p,l,h;    
23     for(int i = 1;i <= n+1;i++) {
24         for(int j = 0;j <= m;j++){
25             dp[i][j] = maxnum;
26         }
27         upp[i-1].high = maxn;
28         upp[i-1].low = -maxn;
29     }
30     for(int i = 1;i <= k;i++){
31         cin>>p>>l>>h;
32         upp[p].high = h;
33         upp[p].low = l;
34         vis[p] = 1;
35     }
36     for(int i =  1;i <= n;i++){
37         for(int j = 1;j <= m;j++){
38             if(j!=m){
39             if(j <= upp[i].low) continue;
40             if(j >= upp[i].high) break;
41             if(j - up[i-1] > 0) dp[i][j] = min(dp[i][j],min(dp[i-1][j-up[i-1]]+1,dp[i][j-up[i-1]]+1));
42             if(j + down[i-1] <= m) dp[i][j] = min(dp[i][j],dp[i-1][j+down[i-1]]);
43             }
44             if(j == m){
45                 for(int q = m-up[i-1] ;q <= m;q++) dp[i][j] = min(dp[i][j],min(dp[i-1][q] + 1,dp[i][q] + 1));
46             }
47             
48         }
49     }
50     int ans = maxnum,key = 1,sea = n-1,sign,acc = 0;
51     for(int i = 1;i <= m;i++) ans = min(ans,dp[n][i]);
52     if(ans == maxnum) key = 0;
53     if(key) cout<<1<<endl<<ans;
54     else{
55         for(;sea >= 0;sea--){
56             for(int i = 1;i <= m;i++){
57                 if(dp[sea][i] < maxnum) sign = 1;
58             }
59             if(sign) break;
60         }
61         for(int i = 0;i < sea;i++) if(vis[i]) acc++;
62         cout<<0<<endl<<acc;
63     }
64     return 0;
65 }
View Code

②照着题解改的满分

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 #include<algorithm>
 6 
 7 using namespace std;
 8 const int maxn = 10005,maxnum = 100000;
 9 struct vain{
10     int high;
11     int low;
12 };
13 
14 int n,m,k,up[maxn],down[maxn],dp[maxn][1005],vis[maxn];
15 vain upp[maxn];
16 int main(){
17     cin>>n>>m>>k;
18     for(int i = 0;i < n;i++){
19         cin>>up[i]>>down[i];
20         
21     }
22     int p,l,h;    
23     for(int i = 1;i <= n+1;i++) {
24         for(int j = 0;j <= m;j++){
25             dp[i][j] = maxnum;
26         }
27         upp[i-1].high = m+1;
28         upp[i-1].low = 0;
29     }
30     dp[0][0] = maxnum;
31     int arrive = k;
32     for(int i = 1;i <= k;i++){
33         cin>>p>>l>>h;
34         upp[p].high = h;
35         upp[p].low = l;
36         vis[p] = 1;
37     }
38     for(int i =  1;i <= n;i++){
39         for(int j = 1;j <= m;j++){
40             if(j >= up[i-1]){
41             dp[i][j] = min(dp[i][j],min(dp[i-1][j-up[i-1]]+1,dp[i][j-up[i-1]]+1));
42             }
43             if(j == m){
44                 for(int q = m-up[i-1] ;q <= m;q++) dp[i][j] = min(dp[i][j],min(dp[i-1][q] + 1,dp[i][q] + 1));
45             }
46             
47         }
48         for(int j = upp[i].low+1;j < upp[i].high;j++) if(j + down[i-1] <=m) dp[i][j] = min(dp[i][j], dp[i-1][j+down[i-1]]);
49         for(int j = 1;j <= upp[i].low;j++) dp[i][j] = maxnum;
50         for(int j = upp[i].high;j <= m;j++) dp[i][j] = maxnum;
51     }
52     int cnt = k, ans = maxnum;
53     for (int i = n; i >= 1; i--) {
54         for (int j = upp[i].low+1; j <= upp[i].high-1; ++j)
55             if (dp[i][j] < maxnum)
56                ans = min(ans, dp[i][j]);
57         if (ans != maxnum) break;
58         if (upp[i].high <= m)
59            cnt --;
60     }
61     if(cnt==k)
62         printf("1\n%d\n", ans);
63     else 
64         printf("0\n%d\n", cnt);
65     return 0;
66 }
View Code

③题解(滚动数组)

技术分享
  1 #include <cmath>
  2 
  3 #include <cstdio>
  4 
  5 #include <cstring>
  6 
  7 #include <cstdlib>
  8 
  9 #include <algorithm>
 10 
 11 
 12 
 13 using namespace std;
 14 
 15 
 16 
 17 const int maxn=1e4+10;
 18 
 19 const int maxm=1e3+10;
 20 
 21 const int INF=0x3f3f3f3f;
 22 
 23 
 24 
 25 int n,m,k,ans;
 26 
 27 int x[maxn],y[maxn];
 28 
 29 int up[maxn],down[maxn];
 30 
 31 int last[maxm],now[maxm];
 32 
 33 
 34 
 35 inline int in(){
 36 
 37 int x=0;char ch=getchar();
 38 
 39 while(ch>9 || ch<0) ch=getchar();
 40 
 41 while(ch>=0 && ch<=9) x=x*10+ch-0,ch=getchar();
 42 
 43 return x; 
 44 
 45 } 
 46 
 47 
 48 
 49 void prework(){
 50 
 51 int t;
 52 
 53 n=in();m=in();k=in();
 54 
 55 for(int i=0;i<n;i++) x[i]=in(),y[i]=in();
 56 
 57 for(int i=0;i<=n;i++) up[i]=m+1,down[i]=0;
 58 
 59 for(int i=1;i<=k;i++){
 60 
 61 t=in();down[t]=in();up[t]=in();
 62 
 63 }
 64 
 65 }
 66 
 67 
 68 
 69 int Min(int a,int b){
 70 
 71 if(a>b) return b;
 72 
 73 return a;
 74 
 75 }
 76 
 77 
 78 
 79 void mainwork(){
 80 
 81 last[0]=INF;
 82 
 83 int i,cnt=0;
 84 
 85 memset(last,0x3f,sizeof(last));
 86 
 87 for(int i=1;i<=m;i++) last[i]=0;
 88 
 89 for(i=1;i<=n;i++){
 90 
 91 memset(now,0x3f,sizeof(now));
 92 
 93 for(int j=x[i-1];j<m;j++)
 94 
 95 now[j]=Min(now[j],last[j-x[i-1]]+1),now[j]=Min(now[j],now[j-x[i-1]]+1); 
 96 
 97 for(int k=m-x[i-1];k<=m;k++)
 98 
 99 now[m]=Min(now[m],last[k]+1),now[m]=Min(now[m],now[k]+1);
100 
101 for(int j=down[i]+1;j<up[i] && j<=m-y[i-1];j++)
102 
103 now[j]=Min(now[j],last[j+y[i-1]]);
104 
105 for(int j=down[i]+1;j<up[i];j++) last[j]=now[j];
106 
107 for(int j=1;j<=down[i];j++) last[j]=INF;
108 
109 for(int j=up[i];j<=m;j++) last[j]=INF;
110 
111 ans=INF;
112 
113 for(int j=down[i]+1;j<up[i];j++) ans=Min(ans,last[j]);
114 
115 if(ans==INF) break;
116 
117 if(up[i]<=m) cnt++;
118 
119 }
120 
121 if(i<=n) printf("0\n%d",cnt);
122 
123 else printf("1\n%d",ans);
124 
125 }
126 
127 
128 
129 int main(){
130 
131 prework();
132 
133 mainwork();
134 
135 return 0;
136 
137 }
View Code

 

 

动态规划——背包

标签:

原文地址:http://www.cnblogs.com/hyfer/p/4842063.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!