每日一题 day21 打卡
Analysis
DP的状态为已经完成的请求数量,通过指派一位服务员
可以把”完成i - 1个请求的状态”转移到”完成i个请求的状态”
那么我们可以知道转移从dp[i - 1] -> dp[i]
dp[i][x][y][z] 代表为第i次选择的情况下,对应的1,2,3号服务员
所对应的位置
那么可以得知
dp[i][arr[i]][y][z] = min(dp[i][arr[i]][y][z], dp[i - 1][x][y][z] + cost[x][arr[i]])
dp[i][x][arr[i]][z] = min(dp[i][x][arr[i]][z], dp[i - 1][x][y][z] + cost[y][arr[i]])
dp[i][x][y][arr[i]] = min(dp[i][x][y][arr[i]], dp[i - 1][x][y][z] + cost[z][arr[i]])
因为肯定有一个位置,继承了上一个的位置
所以保存两个状态就可以了
三种状态转移 pi,x,y
dp[i][x][y] = min(dp[i][x][y], dp[i - 1][x][y] + cost[pi - 1][pi])
dp[i][pi][y] = min(dp[i][pi][y], dp[i - 1][x][y] + cost[x][pi])
dp[i][x][pi] = min(dp[i][x][pi], dp[i - 1][x][y] + cost[y][pi])
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxl 200+10 #define maxn 1000+10 #define INF 2147483647 using namespace std; inline int read() { int x=0; bool f=1; char c=getchar(); for(; !isdigit(c); c=getchar()) if(c=='-') f=0; for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0'; if(f) return x; return 0-x; } inline void write(int x) { if(x<0){putchar('-');x=-x;} if(x>9)write(x/10); putchar(x%10+'0'); } int l,n; int c[maxl][maxl],p[maxn],dp[maxn][maxl][maxl]; signed main() { memset(dp,127,sizeof(dp)); l=read();n=read(); for(int i=1;i<=l;i++) for(int j=1;j<=l;j++) c[i][j]=read(); for(int i=1;i<=n;i++) p[i]=read(); dp[0][1][2]=0; p[0]=3; for(int i=0;i<=n-1;i++) for(int x=1;x<=l;x++) for(int y=1;y<=l;y++) { if(x==y||x==p[i]||y==p[i]) continue; dp[i+1][x][y]=min(dp[i+1][x][y],dp[i][x][y]+c[p[i]][p[i+1]]); dp[i+1][p[i]][y]=min(dp[i+1][p[i]][y],dp[i][x][y]+c[x][p[i+1]]); dp[i+1][x][p[i]]=min(dp[i+1][x][p[i]],dp[i][x][y]+c[y][p[i+1]]); } int ans=INF; for(int i=1;i<=l;i++) for(int j=1;j<=l;j++) ans=min(ans,dp[n][i][j]); write(ans); return 0; }
请各位大佬斧正(反正我不认识斧正是什么意思)