标签:
Wikioi 3729 飞扬的小鸟
输出文件名为 bird.out。
共两行。
第一行,包含一个整数,如果可以成功完成游戏,则输出 1,否则输出 0。
第二行,包含一个整数,如果第一行为 1,则输出成功完成游戏需要最少点击屏幕数,
否则,输出小鸟最多可以通过多少个管道缝隙。
【输入输出样例说明】
如下图所示,蓝色直线表示小鸟的飞行轨迹,红色直线表示管道。
对于 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 }
②照着题解改的满分
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 }
③题解(滚动数组)
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 }
标签:
原文地址:http://www.cnblogs.com/hyfer/p/4842063.html