传送门
题目描述
There are n people and k keys on a straight line. Every person wants to get to the office which is located on the line as well. To do that, he needs to reach some point with a key, take the key and then go to the office. Once a key is taken by somebody, it couldn‘t be taken by anybody else.
You are to determine the minimum time needed for all n people to get to the office with keys. Assume that people move a unit distance per 1 second. If two people reach a key at the same time, only one of them can take the key. A person can pass through a point with a key without taking it.
思路
首先读入后,按照位置分别排序,然后处理一个dis数组,表示第i个人拿了第j把钥匙后去办公室的路程。 然后就是一个01背包,最开始的时候人是瓷的,写了三重循环,一直TLE,附上磁珠代码233333
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<math.h> using namespace std; int n,k,p; int man[1005]; int key[2005]; int dis[1005][2005]; int dp[1005][2005]; inline int cmp(int a,int b){ return a<b; } int minn(int a,int b){ if(a>=b)return b; return a; } int maxx(int a,int b){ if(a>=b)return a; return b; } int main(){ //freopen("1.in","r",stdin); cin>>n>>k>>p; for(register int i=1;i<=n;i++){ cin>>man[i]; } for(register int i=1;i<=k;i++){ cin>>key[i]; } sort(man+1,man+n+1,cmp); sort(key+1,key+k+1,cmp); for(register int i=1;i<=n;i++){ for(register int j=1;j<=k;j++){ dis[i][j]=fabs(man[i]-key[j])+fabs(key[j]-p); dp[i][j]=999999999; } } dp[0][0]=0; //cout<<"fuck"<<endl; for(register int i=1;i<=n;i++){ //1-ige re for(register int j=i;j<=k;j++){ //1-j zhongxuanze int xx=minn(j,n); for(register int kk=i;kk<=xx;kk++){ if(kk<1)continue; dp[i][j]=minn(dp[i][j],maxx(dp[i-1][kk-1],dis[kk][j])); // cout<<i<<‘ ‘<<j<<‘ ‘<<kk<<endl; // cout<<dp[i][j]<<‘ ‘<<dp[i-1][kk]<<‘ ‘<<dis[kk][j]<<endl<<endl; } } } // while(1){ // int x,y; // cin>>x>>y; // cout<<dp[x][y]<<endl; // } int ans=999999999; for(register int i=n;i<=k;i++){ ans=min(ans,dp[n][i]); } cout<<ans<<endl; }
当时用kk来表示i-1个人一共拿到第kk把钥匙是的最大步数的最小值,就是因为枚举这个kk然后挂了,后来发现不需要枚举kk,因为dp[i][j]只能从dp[i][j-1]和dp[i-1][j-1]两种情况转移过来,分别表示不选第j把钥匙和第i个人选了第j把钥匙的情况。
可以得到状态转移方程:
dp[i][j]=min(dp[i][j-1],max(dp[i-1][j-1],dis[i][j]));
还有,初始化很重要qwq,所有的dp[0][i]都等于0,剩下的所有都是2147483647。
附上代码
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<math.h> using namespace std; int n,k,p; int man[1005]; int key[2005]; int dis[1005][2005]; int dp[1005][2005]; inline int cmp(int a,int b){ return a<b; } int minn(int a,int b){ if(a>=b)return b; return a; } int maxx(int a,int b){ if(a>=b)return a; return b; } int main(){ //freopen("1.in","r",stdin); cin>>n>>k>>p; for(register int i=1;i<=n;i++){ cin>>man[i]; } for(register int i=1;i<=k;i++){ cin>>key[i]; } sort(man+1,man+n+1,cmp); sort(key+1,key+k+1,cmp); for(register int i=0;i<=n;i++){ for(register int j=0;j<=k;j++){ dis[i][j]=fabs(man[i]-key[j])+fabs(key[j]-p); dp[i][j]=2147483647; } } for(register int i=0;i<=k;i++){ dp[0][i]=0; } //cout<<"fuck"<<endl; for(register int i=1;i<=n;i++){ //1-ige re for(register int j=1;j<=k;j++){ //1-j zhongxuanze dp[i][j]=minn(dp[i][j-1],maxx(dp[i-1][j-1],dis[i][j])); } } // while(1){ // int x,y; // cin>>x>>y; // cout<<dp[x][y]<<endl; // } int ans=2147483647; for(register int i=n;i<=k;i++){ ans=min(ans,dp[n][i]); } cout<<ans<<endl; }