洛谷链接 UVA1025 练习城市里的间谍 A Spy in the Metro
某城市地铁是一条直线,有 nn(2\leq n\leq 502≤n≤50)个车站,从左到右编号 …n。有 M1辆列车从第 1 站开始往右开,还有 M2 辆列车从第 n 站开始往左开。列车在相邻站台间所需的运行时间是固定的,因为所有列车的运行速度是相同的。在时刻 0,Mario 从第 1 站出发,目的在时刻 T( 2000≤T≤200)会见车站 n 的一个间谍。在车站等车时容易被抓,所以她决定尽量躲在开动的火车上,让在车站等待的时间尽量短。列车靠站停车时间忽略不计,且 Mario 身手敏捷,即时两辆方向不同的列车在同一时间靠站,Mario 也能完成换乘。
就是你从车站1出发在时刻T到达车站n,要求你尽可能在车上,输出最小在车站等待时间
#include
const int oo=0x3f3f3f3f;
using namespace std;
int n,T,M1,M2,kase;
int t[55];
bool trainl[55][10010];//train[i][j]:第i站第j时间是否有train
bool trainr[55][10010];
int dp[10010][55];//dp[i][j]:在时刻i你在车站j最低等多少时间
int main(){
while(cin>>n && n!=0){
kase++;
cin>>T;
memset(t, 0, sizeof(t));
memset(trainl, 0, sizeof(trainl));
memset(trainr, 0, sizeof(trainr));
for(int i=1; i<=n-1; i++) cin>>t[i];//t[i]:i~i+1站时间
cin>>M1;
for(int i=1; i<=M1; i++){
int t1;//左站出发时间
cin>>t1;
int sum=t1;
for(int j=1; j<=n; j++){
trainl[j][sum] = 1;
sum+=t[j];
}
}
cin>>M2;
for(int i=1; i<=M2; i++){
int t2;//右站出发时间
cin>>t2;
int sum=t2;
for(int j=n; j>=1; j--){
trainr[j][sum] = 1;
sum+=t[j-1];
}
}
for(int i=1; i<=n-1; i++)
dp[T][i]=0x3f3f3f3f;
dp[T][n] = 0;
for(int i=T-1; i>=0; i--)
for(int j=1; j<=n; j++){
dp[i][j]=dp[i+1][j]+1;
if(j<n && trainl[j][i] && i+t[j]<=T )
dp[i][j] = min(dp[i][j], dp[i+t[j]][j+1]);
if(j>1 && trainr[j][i] && i+t[j-1]<=T )
dp[i][j] = min(dp[i][j], dp[i+t[j-1]][j-1]);
}
cout<< "Case Number " << kase<< ": ";
if(dp[0][1] >= oo) cout<< "impossible\n";
else cout<<dp[0][1] <<"\n";
}
return 0;
}
洛谷链接 UVA437 巴比伦塔
定义一种塔,只有一个方块的底的两条边严格小于另一个方块的底的两条边,这个方块才能堆在另一个上面。方块可以任意旋转。给出n个方块包含三个尺寸(a , b , c) ,问最高的塔高度是多少
假设我们先不管旋转的问题,考虑每个方块是否能叠起来的问题,那么只有宽严格大于并且长严格大于另一个合法,我们把这种关系变成图上的单项边,把高作为边上的权值,在寻找最高塔的过程中就是找最长路 ,设dp[ i ]为以i为起点的最长路
那么 dp[ i ] = max(dp[j]+1) ( i与j有边)
再考虑旋转的问题,其实就是把一个立方体变成三个立方体,长宽高轮转一下
还有一些细节: 如何建边 1 . 根据上述的关系 构造出一个图来 2 . 一边dp一边暴力判断是否有边(我是这么写的,代码量少)
#include
using namespace std;
const int N = 1e6+7;
typedef long long ll;
struct cube{
int x,y,z;
bool operator > (const cube a)const {
return (x>a.x&&y>a.y)||(x>a.y&&y>a.x);
}// 判断边
}A[1000];
int cnt_cube = 0;
int dp[1000];
int dfs(int ix){ //立方体下标
if(dp[ix]>0) return dp[ix];
dp[ix] = A[ix].z;
for(int i = 0;i<cnt_cube;i++){
if(A[ix]>A[i]){
dp[ix] = max(dp[ix],dfs(i)+A[ix].z);
}
}
return dp[ix];
}
int main(){
int n;
int cass = 1;
while(cin>>n,n){
cnt_cube = 0;
for(int i = 0;i<n;i++){
int a,b,c;
cin>>a>>b>>c;
A[cnt_cube++] = {a,b,c};
A[cnt_cube++] = {a,c,b};
A[cnt_cube++] = {b,c,a};
}
int res = -1;
memset(dp,0,sizeof(dp));
for(int i = 0;i<cnt_cube;i++){ // 以i为起点的最大高度
res = max(res,dfs(i));
}
printf("Case %d: maximum height = %d\n",cass++,res);
}
return 0;
}