POJ 1015 Jury Compromise DP+记录路径

找每个点能转移出去的状态时要回溯到根去掉所有能转移的点来去重。。

可能这种做法在距离根距离较小的时候能用。。(隐隐感觉有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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值