一直WA 应该是有特判没有想到 待解决
这个题的收获:
1 除了dp数组外还可以额外开数组做记录的作用
2 应用了和之前Balance题里一样的思想,平移区间(最开始做的时候直接对cha[i]求了绝对值,其实是错的,动手算一下就会发现先绝对值再加和与先加和再绝对值的结果是不一样的)
3 最后打印结果的时候,要找到差最小的dp数组,注意可能出现距离400距离相等的两种情况,这时候要判断哪边和大。
4 找差最小的dp的时候,注意这个两边找的小技巧,会更快。并且注意i是从0开始取,如果从1开始取,那一些特殊情况(差为0)就会出问题。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
#define MAX_N 1000
int d[MAX_N+10], p[MAX_N+10], he[MAX_N+10], cha[MAX_N+10],/**he cha储存的是每一个人的*/
dp[MAX_N+10][MAX_N+10], path[MAX_N+10][MAX_N+10];
bool check(int i, int j, int k)
{
while(i > 0 && path[i][j] != k)
{
j -= cha[path[i][j]];
i--;
}
return i?false:true;
}
int main()
{
int n, m, t = 0;
while(cin >> n >> m)
{
if(n == 0 && m == 0)
break;
t++;
int flag = 0;
for(int i = 1;i <= n;i++)
{
cin >> p[i] >> d[i];
he[i] = p[i]+d[i];
cha[i] = d[i]-p[i];
//cout << "i=" << i << " cha[i]=" << cha[i] << " he[i]=" << he[i] << endl;
}
//cout << "input finished" << endl;
//attention path[][]也要每轮维护初始值0
memset(path, 0, sizeof(path));
memset(dp, -1, sizeof(dp));
//dp[i][j] 挑选i个人 差为j时和的最大值
dp[0][400] = 0;
for(int i = 1;i <= m;i++)
{
for(int j = 0;j <= 800;j++)
{
if(dp[i-1][j] >= 0)//上一状态存在
{
//cout << "dp[i-1][j]=" << "dp[" <<i-1 <<"]["<<j<<"]=" << dp[i-1][j] << endl;
for(int k = 1;k <= n;k++)
{
if(dp[i][j+cha[k]] < dp[i-1][j]+he[k])
{
if(check(i-1, j, k))
{
dp[i][j+cha[k]] = dp[i-1][j]+he[k];
//cout << "dp[i][j+cha[k]]="<<"dp["<<i<<"]["<<j+cha[k]<<"]="<<dp[i][j+cha[k]]<<endl;
path[i][j+cha[k]] = k;
//cout << "get num="<< k << endl;
//cout << "now i =" << i <<endl;
//cout << "dp[i][j+cha[k]]=" <<dp[i][j+cha[k]] <<endl;
//cout << "j+cha[k]" << j <<" "<<cha[k]<<" "<< j+cha[k] << endl;
}
}
}
}
}
}
//cout << "dp finished" << endl;
int pro = 0, def = 0;
//cout << "vector" << endl;
vector<int> ans;
//cout << "loop" << endl;
for(int i = 0;i <= 400;i++)
{
//cout << dp[m][i] <<endl;
if(dp[m][400+i] >= 0 || dp[m][400-i] >= 0)
{
cout << "Jury #" << t << endl;
int r = 0;
if(dp[m][400+i] > dp[m][400-i])
r = 400+i;
else
r = 400-i;
//cout << r << endl;
int tempm = m;
pro = (dp[m][r] + r - 400) / 2;
def = (dp[m][r] - r + 400) / 2;
while(tempm > 0)
{
ans.push_back(path[tempm][r]);
r -= cha[path[tempm][r]];
tempm--;
}
cout << "Best jury has value " << pro << " for prosecution and value " << def <<" for defence:" << endl;
sort(ans.begin(), ans.end());
for(vector<int>::iterator it = ans.begin();it != ans.end();it++)
{
cout << " " << *it;
}
break;
}
}
ans.clear();
cout << endl << endl;
}
return 0;
}