飞翔的小鸟[背包建模]

[提高] 飞扬的小鸟[组合背包]

飞扬的小鸟

const int maxn=10010;
const int maxm=2010;
int n,m,p;
int x[maxn],y[maxn];//当前位置上升的位置和下降的距离
int low[maxn],high[maxn];//当前位置的上下限制边界
int f[maxn][maxm];//动态规划的转移方程
bool e[maxn];//当前位置有没有经过管道
void solve(){
	//try it again.
	cin>>n>>m>>p;
	up(1,n)cin>>x[o]>>y[o];//输入上升和下降的位置
	up(1,n){
		low[o]=1;//最低不能到地板
		high[o]=m;//最高不能到天花板
	}
	int a,b,c;
	up(1,p){
		cin>>a>>b>>c;
		e[a]=true;//当前位置有管道
		low[a]=++b;//地板上面一个
		high[a]=--c;//天花板下面一个
	}
	mem(f);//未转移到的状态
	up(1,m)f[0][o]=0;//初始化出发的位置
	fup(i,1,n){//按x的位置遍历.类似于背包的转移
		fup(j,x[i]+1,m+x[i]){//上升一次和无限制上升
			f[i][j]=min(f[i-1][j-x[i]]+1,f[i][j-x[i]]+1);
		}
		fup(j,m+1,m+x[i]){//到达天花板上面的归并到天花板
			f[i][m]=min(f[i][m],f[i][j]);
		}
		fup(j,1,m-y[i]){//自然下降
			f[i][j]=min(f[i][j],f[i-1][j+y[i]]);
		}
		fup(j,1,low[i]-1){//不合法的状态设置为无法达到
			f[i][j]=f[0][0];
		}
		fup(j,high[i]+1,m){//不合法的状态设置为无法达到
			f[i][j]=f[0][0];
		}
	}
	int ans=f[0][0];
	up(1,m){
		ans=min(ans,f[n][o]);
	}
	if(ans<f[0][0]){//可以到达最后一列
		cout<<1<<endl;
		cout<<ans<<endl;
	}
	else{//无法到达
		cout<<0<<endl;
		int i,j;
		for(i=n;i>=1;i--){//往回扫经过的管道数
			for(j=1;j<=m;j++){
				if(f[i][j]<f[0][0])break;
			}
			if(j<=m)break;
		}
		ans=0;
		fup(j,1,i)if(e[j])ans++;
		cout<<ans<<endl;
	}
}
posted @ 2023-03-12 00:34  liangqianxing  阅读(32)  评论(0)    收藏  举报