| ||||||||||
| 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