题意:有n个城市,一个人从城市1出发,每天可以选择继续呆在当前城市或者转移到其他城市,第i天呆在第j个城市的收入为in[i][j],从第i个城市转移到第j个城市的费用out[i][j],求m天后的最大收入。
思路:动态规划。dp[i][j]为第i天在(最终停留在)第j个城市获得的最大收入。每个dp[i][j]由遍历dp[i-1][1...n]得到。dp数组可以用滚动数组优化。
#include <stdio.h> #include <string.h> #define N 102 int n,m,dp[N][N]; int out[N][N],in[N][N]; int main(){ freopen("a.txt","r",stdin); while(scanf("%d %d",&n,&m) &&n&&m){ int i,j,k,res,max; for(i = 0;i<n;i++) for(j = 0;j<n;j++) scanf("%d",&out[i][j]); for(i = 0;i<m;i++) for(j = 0;j<n;j++) scanf("%d",&in[i][j]); for(i = 0;i<n;i++) dp[0][i] = in[0][i]-out[0][i]; for(i = 1;i<m;i++){ for(j = 0;j<n;j++){ max = dp[i-1][0]+in[i][j]-out[0][j]; for(k = 1;k<n;k++){ int temp = dp[i-1][k]+in[i][j]-out[k][j]; max = max>temp?max:temp; } dp[i][j] = max; } } res = dp[m-1][0]; for(i = 1;i<n;i++) res = res>dp[m-1][i]?res:dp[m-1][i]; printf("%d\n",res); } return 0; }
思路:动态规划,枚举第一个点集的每一个点,设为起始点,然后动归即可。复杂度O(n*s^3)。
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <queue> using namespace std; #define INF 0x3fffffff #define clr(s,t) memset(s,t,sizeof(s)) #define N 105 #define M 42 double s[N][M][M],dp[N][M]; int num[N]; int n; struct node{ int x,y; }p[N][M]; double dist(struct node a,struct node b){ return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y)); } int main(){ int i,j,k,a; int res = INF; scanf("%d",&n); for(i = 1;i<=n;i++){ scanf("%d",&num[i]); for(j = 1;j<=num[i];j++) scanf("%d %d",&p[i][j].x,&p[i][j].y); } for(i = 1;i<n;i++) for(j = 1;j<=num[i];j++) for(k = 1;k<=num[i+1];k++) s[i][j][k] = dist(p[i][j],p[i+1][k]); for(j = 1;j<=num[n];j++) for(k = 1;k<=num[1];k++) s[n][j][k] = dist(p[n][j], p[1][k]); for(a = 1;a<=num[1];a++){ for(i = 1;i<=num[2];i++) dp[2][i] = s[1][a][i]; for(i = 3;i<=n;i++) for(j = 1;j<=num[i];j++){ dp[i][j] = INF; for(k = 1;k<=num[i-1];k++) dp[i][j] = min(dp[i][j],dp[i-1][k]+s[i-1][k][j]); } for(i = 1;i<=num[n];i++) res = min(res,(int)(100*(dp[n][i]+s[n][i][a]))); } printf("%d\n",res); return 0; }