机器分配

说是泛化背包,其实很简单啦,就是找最小字典序路径很讨厌

不过 倒序做就不会有这个烦恼了

 

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
#define dec(i,l,r) for(int i=l;i>=r;--i) 
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

int n,m,ans[20][20],f[20][20],last[20][20],b[20],c[20],cnt;
int a[20][20];
inline bool check(int i,int j,int k)
{
    b[i]=f[i][j];c[i]=f[i][k];
    if(i==1)
    {
        inc(i,1,cnt)
        if(b[i]<c[i])re 1;
        else if(b[i]>c[i])re 0;
    }
    check(i-1,last[i][j],last[i][k]);
}

inline void dfs(int i,int j)
{
    if(!i)re ;
    dfs(i-1,last[i][j]);
    printf("%d %d\n",i,f[i][j]);
}
int main()
{
    rd(n),rd(m);
    
    inc(i,1,n)inc(j,1,m)
    rd(a[i][j]);
    
    inc(j,1,m)ans[1][j]=a[1][j],f[1][j]=j;
    
    inc(i,2,n)
    {    
    cnt=i-1;
        inc(j,1,m)//前i家店共选了j个机器 
        {
            ans[i][j]=ans[i-1][j];
            last[i][j]=j;//前i-1家店选了j个机器 
            
            inc(k,1,j)//第i家店选k个机器 
            {
                if(ans[i][j]<ans[i-1][j-k]+a[i][k])
                {
                    ans[i][j]=ans[i-1][j-k]+a[i][k];
                    f[i][j]=k;
                    last[i][j]=j-k;
                } 
                else if(ans[i][j]==ans[i-1][j-k]+a[i][k])
                {
                    if(check(i-1,last[i][j],j-k))continue;
                    f[i][j]=k;
                    last[i][j]=j-k;
                }
            } 
        }
    }

    printf("%d\n",ans[n][m]); 
    
    dfs(n,m);
    re 0;
} 

 

posted @ 2019-08-13 21:02  凉如水  阅读(259)  评论(0编辑  收藏  举报