SGU 104. Little shop of flowers: http://acm.sgu.ru/problem.php?contest=0&problem=104
题意:给你F支花和V个花瓶,再给出一个F*V的矩阵,表示第i支花插到第j个瓶子所得到的魅力值,插花的时候有两个规则
1.编号小的花一定要放在编号大的花的前面。 2.所有花全部都要放完。
问所能达到的最大的魅力值及达到此魅力值的放置方法。
思路:使用动态规划的方法。
dp定义:dp[i][j] 将剩下的第i~F支花插入到第j~V个花瓶上时的最大值
dp转移方程:dp[i][j]=max(dp[i][j],dp[i+1][k+1]+cc[i][k]) j<=k<=V-(F-i-1)(保证每个花都有位置放)
用这个dp的方法可以求出来最大值,但是该如何输出放置的方法呢?
对于一般的dp问题的方案输出,我们可以用一个数组来记录他是又哪一个状态转移过来的,这样的迭代下去我们就能知道最优的方案了~~~~。
code:
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#define INF 100000000
using namespace std;
const int maxn=200;
int dp[maxn][maxn];
int fp[maxn][maxn];
int cc[maxn][maxn];
int F,V;
int dfs(int x,int y)
{
if(x>=F) return 0;
if(y>=V) return -INF;
if(dp[x][y]!=0) return dp[x][y];
int res=0,pos=-1;
for(int k=y;k<V-(F-x-1);k++){
if(dfs(x+1,k+1)+cc[x][k]>=res){
res=dp[x+1][k+1]+cc[x][k];
pos=k;
}
}
dp[x][y]=res;
fp[x][y]=pos;
return dp[x][y];
}
int main()
{
int pos;
while(scanf("%d%d",&F,&V)!=EOF){
for(int i=0;i<F;i++) for(int j=0;j<V;j++){scanf("%d",&cc[i][j]); cc[i][j]+=50;}
memset(dp,0,sizeof(dp));
memset(fp,-1,sizeof(fp));
printf("%d\n",dfs(0,0)-F*50);
pos=fp[0][0];
printf("%d",pos+1);
for(int i=1;i<F;i++){
pos=fp[i][pos+1];
printf(" %d",pos+1);
}
printf("\n");
}
return 0;
}