GDG破产了,但是她有一些追随者,追随者会资助她一些钱。她在每个追随者的房间住一晚上就可以得到一些钱,在第i个人的房间住的第一个晚上可以获得ai,如果一直不离开这个房间的话,第二个晚上可以获得bi,之后每个晚上都可以获得ci(这题目真没节操...)。每天白天她都可以移动,但因为她有一些行李,所以她无法自己从某个房间移动到其他房间,但是第i个房间的追随者可能会允许以收一定的钱为代价帮她把行李搬到某个特定的其他的房间。移动没有次数限制,即一天可以移动多次,并且可以移动回最原来的房间,以获得ai的钱。最开始GDG在0号房间。问她在第l个晚上之前最多可以得到多少钱?
数据范围:最多100个房间,最多100天,每个钱数都不超过10^4所以总共不会超过int。
首先Floyd求从任意房间到任意房间的移动代价。
然后dp求解,定义状态dp[i][j]为第i天结束时在j号房间所能够达到的最大钱数。每次转移的时候先枚举这天所有的移动的可能性(100*100),计算出第i天的白天移动到第i号房间后所能达到的最大钱数,然后枚举在这个房间呆的天数。
#include <cstdio>
#include <cstring>
int n,d;
int dis[100][100],dis2[100];
int a[100],b[100],c[100];
int dp[101][100];
inline void update(int &a,int b) {
if (a==-1||a<b) a=b;
}
int main() {
int i,j,k,m,x,y;
while (scanf("%d%d",&n,&d)!=EOF) {
memset(dis,-1,sizeof(dis));
for (i=0;i<n;i++) {
scanf("%d%d%d",&a[i],&b[i],&c[i]);
scanf("%d",&m);
for (j=0;j<m;j++) {
scanf("%d%d",&x,&y);
dis[i][x]=y;
}
}
for(k=0;k<n;k++)
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if (dis[i][k]!=-1&&dis[k][j]!=-1&&(dis[i][j]==-1||dis[i][j]>dis[i][k]+dis[k][j]))
dis[i][j]=dis[i][k]+dis[k][j];
memset(dp,-1,sizeof(dp));
dp[0][0]=0;
update(dp[1][0],a[0]);
update(dp[2][0],a[0]+b[0]);
int tmp=a[0]+b[0]+c[0];
for (k=3;k<d;k++) {
update(dp[k][0],tmp);
tmp+=c[0];
}
for (i=1;i<d-1;i++) {
memset(dis2,-1,sizeof(dis2));
for (j=0;j<n;j++)
if (dp[i][j]!=-1)
for (k=0;k<n;k++) {
if (dis[j][k]>=0) {
int tmp=dp[i][j]-dis[j][k];
if (tmp>=0) update(dis2[k],tmp);
}
}
for (j=0;j<n;j++) {
if (dis2[j]!=-1) {
update(dp[i+1][j],dis2[j]+a[j]);
update(dp[i+2][j],dis2[j]+a[j]+b[j]);
int tmp=dis2[j]+a[j]+b[j]+c[j];
for (k=i+3;k<d;k++) {
update(dp[k][j],tmp);
tmp+=c[j];
}
}
}
}
int ans=-1;
for (j=0;j<n;j++) {
update(ans,dp[d-1][j]);
}
printf("%d\n",ans);
}
return 0;
}