分析:因为时间是单向流逝的,是天然的"序",所以影响决策的只有当前时间和所处的决策。dp[i][j],表示在第i分钟时,处于第j个车站,最少还需要多少等待时间,因此其等待时间就有站原地等待,乘坐从左到右的车,乘坐从右到左的车,三个状态来决定。
1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "string" 5 using namespace std; 6 const int maxn=1000+100; 7 const int maxm=10000+100; 8 const int INF=1<<30; 9 int n,T,m1,m2; 10 int t[maxn],d[maxn],e[maxn]; 11 int dp[maxm][60],vis[maxm][60][3]; 12 int main() 13 { 14 int cas=0; 15 while(cin>>n) 16 { 17 if(n==0) break; 18 cin>>T; 19 memset(vis,0,sizeof(vis)); 20 memset(dp,0,sizeof(dp)); 21 memset(t,0,sizeof(t)); 22 for(int i=1;i<n;i++) 23 cin>>t[i]; 24 cin>>m1; 25 for(int i=1;i<=m1;i++) 26 cin>>d[i]; 27 cin>>m2; 28 for(int i=1;i<=m2;i++) 29 cin>>e[i]; 30 //从左到右 31 for(int i=1;i<=m1;i++){ 32 int cnt=d[i]; 33 for(int j=1;j<=n;j++){ 34 vis[cnt][j][0]=1; 35 cnt+=t[j]; 36 } 37 } 38 //从右到左 39 for(int i=1;i<=m2;i++){ 40 int res=e[i]; 41 for(int j=n;j>=1;j--){ 42 vis[res][j][1]=1; 43 res+=t[j-1]; 44 } 45 } 46 47 for(int i=1;i<n;i++) dp[T][i]=INF; 48 dp[T][n]=0; 49 for(int i=T-1;i>=0;i--){ 50 for(int j=1;j<=n;j++){ 51 dp[i][j]=dp[i+1][j]+1; 52 if(j<n&&vis[i][j][0]&&(i+t[j]<=T)) //从左到右 53 dp[i][j]=min(dp[i][j],dp[i+t[j]][j+1]); 54 if(j>1&&vis[i][j][1]&&(i+t[j-1]<=T)) 55 dp[i][j]=min(dp[i][j],dp[i+t[j-1]][j-1]); 56 } 57 } 58 printf("Case Number %d: ",++cas); 59 if(dp[0][1]>=INF) cout<<"impossible"<<endl; 60 else cout<<dp[0][1]<<endl; 61 62 } 63 return 0; 64 }
分析:如果j能够放在i上面,从i向j连边,最后求最大高度,dfs(i)表示从第i个开始的最长距离,注意处理三个长方体三个不同面的技巧
1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "string" 5 using namespace std; 6 const int maxn=100; 7 int n; 8 struct Node{ 9 int x,y,z; 10 }; 11 Node p[maxn]; 12 int g[maxn][maxn]; 13 bool judge(int a,int b){ 14 if((min(p[a].x,p[a].y)>min(p[b].x,p[b].y))&&(max(p[a].x,p[a].y)>max(p[b].x,p[b].y))) 15 return true; 16 return false; 17 } 18 int dp[maxn]; 19 int dfs(int i){ 20 int& ans=dp[i]; 21 if(ans!=-1) return ans; 22 ans=p[i].z; 23 for(int j=1;j<=n;j++){ 24 if(g[i][j]) 25 ans=max(ans,dfs(j)+p[i].z); 26 } 27 return ans; 28 } 29 int main() 30 { 31 //freopen("a.txt","r",stdin); 32 //freopen("a.out","w",stdout); 33 int cas=0; 34 while(cin>>n) 35 { 36 if(n==0) break; 37 for(int i=1;i<=n;i++){ 38 cin>>p[i].x>>p[i].y>>p[i].z; 39 p[i+n].x=p[i].y,p[i+n].y=p[i].z,p[i+n].z=p[i].x; 40 p[i+2*n].x=p[i].z,p[i+2*n].y=p[i].x,p[i+2*n].z=p[i].y; 41 } 42 n*=3; 43 memset(g,0,sizeof(g)); 44 for(int i=1;i<=n;i++){ 45 for(int j=1;j<=n;j++){ 46 if(judge(i,j)) 47 g[i][j]=1; 48 } 49 } 50 memset(dp,-1,sizeof(dp)); 51 int ans=0; 52 for(int i=1;i<=n;i++){ 53 ans=max(ans,dfs(i)); 54 } 55 printf("Case %d: maximum height = ",++cas); 56 cout<<ans<<endl; 57 } 58 }
分析:根据坐标是按照x排序的,所以这个问题肯定是个单向的,即一次不可能先选择i+2,再选择i+1。所以我们设dp[i][j]为已经选取了1-max(i,j)当中的所有元素,同时第一个位于i,第二个位于j时,还需要在走的最少距离。则dp[i][j]必然来自于dp[i+1][j](第一个走i+1),dp[i+1][i](第二个走i+1),两种决策当中的最小值,处理一下边界即可,非常经典的一个题
1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "string" 5 #include "cmath" 6 using namespace std; 7 const int maxn=10000; 8 const double INF=1<<30; 9 struct Node 10 { 11 int x,y; 12 }; 13 Node p[maxn]; 14 double dp[maxn][maxn]; 15 int n; 16 double dist(int x1,int y1,int x2,int y2){ 17 int num=(x1-x2)*(x1-x2); 18 int ans=(y1-y2)*(y1-y2); 19 double res=sqrt((double)num+(double)ans); 20 return res; 21 } 22 int main() 23 { 24 while(cin>>n){ 25 if(n==0) break; 26 for(int i=1;i<=n;i++){ 27 cin>>p[i].x>>p[i].y; 28 } 29 for(int i=1;i<=n;i++) 30 dp[n][i]=dist(p[i].x,p[i].y,p[n].x,p[n].y); 31 for(int i=1;i<=n;i++){ 32 dp[n-1][i]=dist(p[n-1].x,p[n-1].y,p[n].x,p[n].y)+dist(p[i].x,p[i].y,p[n].x,p[n].y); 33 } 34 for(int i=n-2;i>=2;i--){ 35 for(int j=1;j<i;j++) 36 dp[i][j]=min(dp[i+1][j]+dist(p[i+1].x,p[i+1].y,p[i].x,p[i].y),dp[i+1][i]+dist(p[j].x,p[j].y,p[i+1].x,p[i+1].y)); 37 } 38 double res=dist(p[1].x,p[1].y,p[2].x,p[2].y)+dp[2][1]; 39 printf("%.2f ",res); 40 } 41 return 0; 42 }