找每个点能转移出去的状态时要回溯到根去掉所有能转移的点来去重。。
可能这种做法在距离根距离较小的时候能用。。(隐隐感觉有bug,还是人云亦云地做掉先了。。)
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
template <class T>
inline bool rd(T &ret) {
char c; int sgn;
if(c=getchar(),c==EOF) return 0;
while(c!='-'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
ret*=sgn;
return 1;
}
template <class T>
inline void pt(T x) {
if (x <0) {
putchar('-');
x = -x;
}
if(x>9) pt(x/10);
putchar(x%10+'0');
}
const int N = 205;
const int M = 25;
using namespace std;
int n, m;
int a[N], b[N];
int dp[M][805], pre[M][805], id[M][805];
bool vis[N];
vector<int>path;
void output_path(){
sort(path.begin(), path.end());
for(int i = 0; i < (int)path.size(); i++)printf(" %d", path[i]);puts("");
}
void find(int x, int y){
path.clear();
while(-1 != pre[x][y]){
path.push_back(id[x][y]);
vis[id[x][y]] = 1;
int tx = pre[x][y]/1000;
int ty = pre[x][y]%1000;
x = tx; y = ty;
}
}
const int mov = 400;
void work(){
memset(dp, -1, sizeof dp);
dp[0][mov] = 0; pre[0][mov] = -1;
for(int i = 0; i < m; i++)
for(int j = 0; j <= 800; j++)
{
if(-1 == dp[i][j])continue;
memset(vis, 0, sizeof vis);
find(i, j);
// output_path();
for(int k = 1; k <= n; k++)
if(0 == vis[k])
{
int tmp = a[k]-b[k];
if(dp[i+1][j+tmp] < dp[i][j] + a[k]+b[k])
{
dp[i+1][j+tmp] = dp[i][j] + a[k]+b[k];
pre[i+1][j+tmp] = i*1000+j;
id[i+1][j+tmp] = k;
}
}
}
}
int main(){
int Cas = 1;
while(~scanf("%d %d", &n, &m), n+m){
for(int i = 1; i <= n; i++)rd(a[i]), rd(b[i]);
printf("Jury #%d\n", Cas++);
work();
int ans = -1;
for(int i = 400; i <= 800; i++)
if(-1 != dp[m][i] || -1 != dp[m][800-i])
{
if(dp[m][i] > dp[m][800-i])
ans = i;
else ans = 800-i;
break;
}
printf("Best jury has value %d for prosecution and value %d for defence:\n", (dp[m][ans]+ans-400)/2, (dp[m][ans]-ans+400)/2);
find(m, ans);
output_path();
puts("");
}
return 0;
}