转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题意 :有一个人,每天可以得到a[i]个食物,他自己每天必须要满足v个食物,而且a[i]>=v,他有m个朋友,每个朋友会有一段时间呆在他家里,每个朋友也有个食物需求量,他可以选择给朋友食物,也可以不给,但是如果给的话,就必须满足朋友的食物需求,每满足一次威信+1,每个朋友每天只能满足一次。
当然首先要保证自己吃了
食物有个保持期为两天,也就是当天的食物,可以留到明天再吃,但是后天就不能要了
食物有个保质期,使得本题看上去不好办
如果保质期为1天的话,肯定为贪心。
和yobobobo讨论了下
得出DP的做法
dp[i][j]表示前i天,还剩下j个食物能得到威信的最优值。
转移的时候需要贪心,首先转移一次当天不给任何 一个朋友食物的状态
然后按所有朋友按需求贪心,如果我要满足一个朋友,当然选择需求小的,枚举所有朋友,转移即可。
然后顺带记录下路径就OK了吧。
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<queue>
#define inf 1600005
#define M 40
#define N 100005
#define maxn 2000005
#define eps 1e-7
#define zero(a) fabs(a)<eps
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define MOD 1000000007
#define lson step<<1
#define rson step<<1|1
#define sqr(a) ((a)*(a))
#define Key_value ch[ch[root][1]][0]
#define test puts("OK");
#define pi acos(-1.0)
#define lowbit(x) ((x)&(-(x)))
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define vi vector<int>
using namespace std;
struct Node{
int l,r,f,id;
bool operator<(const Node n)const {
return f<n.f;
}
}fri[405];
int dp[405][405];
int pre[405][405];
vector<int>path[405][405];
int n,v,a[405]={0},m;
int main(){
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
while(scanf("%d%d",&n,&v)!=EOF){
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
mem(dp,-1);mem(pre,-1);
scanf("%d",&m);
for(int i=0;i<m;i++){
scanf("%d%d%d",&fri[i].l,&fri[i].r,&fri[i].f);
fri[i].id=i+1;
}
sort(fri,fri+m);
dp[0][0]=0;
for(int i=0;i<n;i++){
for(int j=0;j<=a[i];j++){
if(dp[i][j]==-1) continue;
int num=j+a[i+1]-v;
if(dp[i+1][min(num,a[i+1])]<dp[i][j]){
dp[i+1][min(num,a[i+1])]=dp[i][j];
pre[i+1][min(num,a[i+1])]=j;
path[i+1][min(num,a[i+1])].clear();
}
dp[i+1][min(num,a[i+1])]=max(dp[i+1][min(num,a[i+1])],dp[i][j]);
int cnt=0;
vector<int> eat;eat.clear();
for(int k=0;k<m;k++){
if(i+1<fri[k].l||i+1>fri[k].r) continue;
if(num<fri[k].f) break;
num-=fri[k].f;cnt++;
eat.pb(fri[k].id);
if(dp[i+1][min(num,a[i+1])]<dp[i][j]+cnt){
dp[i+1][min(num,a[i+1])]=dp[i][j]+cnt;
pre[i+1][min(num,a[i+1])]=j;
path[i+1][min(num,a[i+1])]=eat;
}
}
}
}
int ans=-1,idx;
vector<int>ret;
for(int i=0;i<=a[n];i++){
if(dp[n][i]>ans) ans=dp[n][i],idx=i;
}
printf("%d\n",ans);
for(int i=n;i>0;i--){
ret.pb(idx);
idx=pre[i][idx];
}
for(int i=n-1;i>=0;i--){
idx=ret[i];
printf("%d",path[n-i][idx].size());
for(int j=0;j<path[n-i][idx].size();j++) printf(" %d",path[n-i][idx][j]);
printf("\n");
}
}
return 0;
}