• POJ 1015



    新赛季的开始!

    (POJ 1015)

    前言

    (dp) 一般是用于求解最后的值,这个 (dp) 不同于以往的 (dp) ,它需要求解之前的状态,在 (dp) 状态转移的过程中,它的结果总是在不断地移动,在求解完之后,搜索之前的状态时,前面的值已经发生改变,所以需要在状态转移的时候就应该对结果进行保存,这也就是这个题的坑之处,写了一下午。

    题解

    这个题是一个背包问题,也不能说是背包就是的一些状态转移类型,比较容易理解,坑就在于搜索解。

    [dp[i][j] = max(dp[i-(l[k]-r[k])][j-1]) ]

    这个状态转移方程就是根据之前的结果对于添加这个物品之后状态求解最小值,在求解的过程中趁机对物品状态进行保存,然后特别注意一个样例

    输入

    1 1
    0 0 
    0 0
    

    输出

    Jury #1
    Best jury has value 0 for prosecution and value 0 for defence:
     1
    
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int MAXN = 2e3+5;
    int vis[MAXN][21],dis[MAXN][21];
    int l[205],r[205];
    int sum[MAXN][21][2];
    vector<int>v[MAXN][21];
    inline int min(int a,int b){return a<b?a:b;}
    // inline int abs(int a){return a<0?-a:a;}
    void slove(int x,int y,int dx,int dy){
    	v[dx][dy].clear();
    	for(int i=0;i<(int)v[x][y].size();++i)
    		v[dx][dy].push_back(v[x][y][i]);
    	sum[dx][dy][0]=sum[x][y][0];
    	sum[dx][dy][1]=sum[x][y][1];
    }
    int main(){
    	int n,m,times=1;
    	while(scanf("%d%d",&n,&m)!=EOF&&(n+m)){
    		memset(vis,0,sizeof(vis));
    		memset(dis,0,sizeof(dis));
    		memset(sum,0,sizeof(sum));
    		vis[400][0]=1;
    		for(int i=1;i<=n;++i){
    			scanf("%d%d",&l[i],&r[i]);
    			int d=l[i]-r[i];	
    			for(int j=m;j>0;--j){
    				for(int k=0;k<=800;++k){
    					if(k+d>=0&&d+k<=800&&vis[k][j-1]){
    						if(dis[k+d][j]<=dis[k][j-1]+r[i]+l[i]){
    							vis[k+d][j]=i;
    							dis[k+d][j]=dis[k][j-1]+r[i]+l[i];
    							slove(k,j-1,k+d,j);
    							v[k+d][j].push_back(i);
    							sum[k+d][j][0]+=l[i];
    							sum[k+d][j][1]+=r[i];
    							// printf("%d
    ",k+d);
    							// for(int b=0;b<(int)v[k+d].size();++b)
    							// 	printf("%d ",v[k+d][b]);
    							// printf("
    ");
    						}
    					}
    				}
    			}
    		}
    		// printf("%d
    ",vis[400][1]);
    		int minn=2000,L=0,R=0;
    		for(int i=0;i<=1000;++i){
    			if(vis[i][m]){
    				if(abs(minn)==abs(i-400)){
    					if(L+R<=sum[i][m][0]+sum[i][m][1]){
    						L=sum[i][m][0];
    						R=sum[i][m][1];
    						minn=i-400;
    					}
    				}
    				if(abs(minn)>abs(i-400)){
    					minn=i-400;
    					L=sum[i][m][0];
    					R=sum[i][m][1];
    				}
    			}
    		}
    		printf("Jury #%d 
    Best jury has value %d for prosecution and value %d for defence: 
    ",times,L,R);
    		for(int i=0;i<(int)v[minn+400][m].size();++i)
    			printf(" %d",v[minn+400][m][i]);
    		printf("
    
    ");
    		++times;
    	}
    	return 0;
    }
    
    新赛季的开始
  • 相关阅读:
    linux清理内存
    华为代码注释标准
    Spring缓存机制的理解
    jQuery实现动态分割div—通过拖动分隔栏实现上下、左右动态改变左右、上下两个相邻div的大小
    模仿iframe框架,由分隔栏动态改变左右两侧div大小———基于jQuery
    js实现由分隔栏决定两侧div的大小—js动态分割div
    java基于socket的简单聊天系统
    中国移动归属地区号大全
    将本地光盘做成yum源
    windows下设置计划任务自动执行PHP脚本
  • 原文地址:https://www.cnblogs.com/VagrantAC/p/12739526.html
Copyright © 2020-2023  润新知