題解 P1854 花店櫥窗布置


把二維壓成一維的DP了解一下。。。

傳送門

(以紀念神經兮兮調了兩天的一維DP(刷水題謀財害命)以及感謝學長的幫助@ydnhaha

顯然我們有二維的dp:f[i][j]代表第i盆花放到第j個位置

for(R i=1;i<=n;i++) 
    for(R j=V-(n-i);j>=i;j--) 
        for(R k=j-1;k>=i-1;k--) 
            if(f[i][j]<f[i-1][k]+w[i][j])
                ans[i][j]=k,f[i][j]=f[i-1][k]+w[i][j];

 

由於只訪問上一個狀態,我們可以理所應當的把它壓掉

注意,需要倒序循環(好吧我的二維的也是倒序的QWQ)

for(R i=1;i<=n;i++) for(R j=V-(n-i);j>=i;j--) {
        f[j]=0xcfcfcfcf;
        for(R k=j-1;k>=i-1;k--) if(f[j]<f[k]+w[i][j]) ans[i][j]=k,f[j]=f[k]+w[i][j];
}

時間復雜度不變但是空間小了一些?

AC代碼

二維的:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define R register int
using namespace std;
int n,V,pos=109;
int w[110][110],f[110][110],ans[110][110];

inline void print(int i,int j) {
    if(!i) return ;
    print(i-1,ans[i][j]);
    printf("%d ",j);
}

signed main() {
//freopen("testdata.in","r",stdin);
    memset(f,0xcf,sizeof(f));
    scanf("%d%d",&n,&V);f[n][109]=0xcfcfcfcf;
    for(R i=1;i<=n;i++) for(R j=1;j<=V;j++) scanf("%d",&w[i][j]); 
    for(R i=0;i<=V;i++) f[0][i]=0;
    for(R i=1;i<=n;i++) for(R j=V-(n-i);j>=i;j--) 
        for(R k=j-1;k>=i-1;k--) if(f[i][j]<f[i-1][k]+w[i][j]) ans[i][j]=k,f[i][j]=f[i-1][k]+w[i][j];//,cout<<i<<" "<<j<<" "<<k<<" "<<f[1][1]<<endl;
    for(R i=V;i>=n;i--) if(f[n][i]>f[n][pos]) pos=i;
    printf("%d\n",f[n][pos]),print(n,pos);
}

 

一維的:

(其實一維的有點像01背包對吧)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define R register int
using namespace std;
int n,V,pos=109;
int w[110][110],f[110],ans[110][110];

inline void print(int i,int j) {
    if(!i) return ;
    print(i-1,ans[i][j]);
    printf("%d ",j);
}

signed main() {
    //freopen("testdata.in","r",stdin);
    //memset(f,0xcf,sizeof(f));
    scanf("%d%d",&n,&V);f[109]=0xcfcfcfcf;
    for(R i=1;i<=n;i++) for(R j=1;j<=V;j++) scanf("%d",&w[i][j]); 
    //for(R i=0;i<=V;i++) f[0][i]=0;
    for(R i=1;i<=n;i++) for(R j=V-(n-i);j>=i;j--) {
        f[j]=0xcfcfcfcf;
        for(R k=j-1;k>=i-1;k--) if(f[j]<f[k]+w[i][j]) ans[i][j]=k,f[j]=f[k]+w[i][j];//,cout<<i<<" "<<j<<" "<<k<<" "<<f[1][1]<<endl; 
    }
    for(R i=V;i>=n;i--) if(f[i]>f[pos]) pos=i;
    printf("%d\n",f[pos]),print(n,pos);
}

 2019.3.3


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com