Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
我被此题和VS2008玩疯了调试啊,调试ING。 三重循环,看得眼睛都痛了。 /* 我的方法是DP, 定义一个数组:a[205][25][-450..450]; a[i][j][k]:前i个人中,选J个人,D(i) - P(i)差值为K时的最大和。 对于第i个人,显然我们可以不选他,即:a[i-1][j][k],也可以选他,即:a[i-1][j-1][k-D(i)+P(i)]+D(i)+P(i); 所以得动态转移方程:a[i][j][k]=max{a[i-1][j][j] ,a[i-1][j-1][k-D(i)+P(i)]+D(i)+P(i)}; 这样我们就能保证其和最大。 考虑到a[i]只与前面的a[i-1]有关,于是可以用滚动数组来做,否则会MLE。。。 选的时候让k从0到400循环,碰到可以构成的a[n][m][k]即跳出, 此时D(i) - P(i)差最小。而此时的a[n][m][k]值即是其最大的和。 关于路径的记录,我们开个 bool used[205][25][-450..450]; 把每次计算时的选择记录下来就行了。输出的时候就根据每次的选择倒过来走。 当然C语言中数组不允许下标为负数,所以我们只能定义成a[205][25][850];这样,然后每次给他加上400再用即可。 */ #include <iostream> #include <vector> #include <cmath> using namespace std; const int MAX=1023; const int UNUSED=1023; int d[205],p[205]; static bool used[205][25][805]; void output(int i,int j,int tk) { if(i==j) { for(int w=1;w<=i;w++) { cout<<w<<' '; } } else { if(used[i-1][j][tk]) { output(i-1,j,tk); } else if(used[i-1][j-1][tk-d[i]+p[i]]) { output(i-1,j-1,tk-d[i]+p[i]); cout<<i<<' '; } } return; } int main() { int m,n; cin>>m>>n; for(int t=1;t<=m;t++) { cin>>p[t]>>d[t]; } int dptable[2][25][805];//保存动态规划状态的结果,循环保存 [i][][] 和 [i+1][][] 的状态值 memset(dptable,UNUSED,2*25*805);//初始化为未使用 memset(used,false,205*25*805); for(int count=1;/*为i计数,直到m*/count<=n; count++) { int i=count%2; int next=i?0:1; //这里填入初始化数组 int tpk=0; int sum=0; for(int x=1;x<=i;x++) { tpk+=p[i]; } sum=tpk; for(int x=1;x<=i;x++) { tpk-=d[i]; sum+=d[i]; } dptable[i][i][tpk]=sum;//以上为i选i填表 dptable[i][0][0]=0;//以上为i选1填表 for(int j=1;j<=i; j++) { for(int k=0;k<=20*j; k++) { int tpk= k +400; if(dptable[i][j][tpk] <= dptable[i][j-1][tpk-d[i]+p[i]]+d[i]+p[i]) { dptable[next][j][tpk]=dptable[i][j][tpk];//状态转化函数 used[count][j][tpk]=true; } else { dptable[next][j][tpk]=dptable[i][j-1][tpk-d[i]+p[i]]+d[i]+p[i]; used[count][j-1][tpk-d[i]]=true; } int tpk2= -k +400; if(dptable[i][j][tpk2] <= dptable[i][j-1][tpk2-d[i]+p[i]]+d[i]+p[i]) { dptable[next][j][tpk2]=dptable[i][j][tpk2];//状态转化函数 used[count][j][tpk2]=true; } else { dptable[next][j][tpk]=dptable[i][j-1][tpk-d[i]+p[i]]+d[i]+p[i]; used[count][j-1][tpk-d[i]]=true; } if(count==n && j==m && (dptable[next][j][tpk]<1000||dptable[next][j][tpk2]<1000))//完成算法 { if(dptable[next][j][tpk]<dptable[next][j][tpk2]) { output(next,j,tpk); } else { output(next,j,tpk2); } } } } } return 0; } Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator