【2019.9.23】NOIP2017 practice exam

Problem

Solution

T1.

T2.

f[i][j]表示原串使用了前i个字符,添加了j个字符后的总代价。

同时记录上一次使用的决策是哪一个。

复杂度是O((n+k)*k)。

#include<bits/stdc++.h>
using namespace std;
const int N=10005;
const int K=55;
int n,k,f[N][K],lst[N][K];
char str[N];
inline void get(int x,int y){
    if(lst[x][y]==1) get(x-1,y);
    else if(lst[x][y]==2){
        get(x,y-1);
        printf(" %d",x+y);
    }
}
inline void dp(){
    int i,t;
    memset(f,0x3f,sizeof(f));
    f[0][0]=0;
    for(int a=1;a<=n+k;a++){
        for(int j=max(0,a-n);j<=min(a,k);j++){
            i=a-j;
            t=((a%10)==0);
            if(i&&j){
                if(f[i][j]>f[i-1][j]+(t&(str[i]=='1'))){
                    f[i][j]=f[i-1][j]+(t&(str[i]=='1'));
                    lst[i][j]=1;
                }
                if(f[i][j]>f[i][j-1]+t){
                    f[i][j]=f[i][j-1]+t;
                    lst[i][j]=2;
                }
            }
            else if(i){
                f[i][j]=f[i-1][j]+(t&(str[i]=='1'));
                lst[i][j]=1;
            }
            else{
                f[i][j]=f[i][j-1]+t;
                lst[i][j]=2;
            }
        }
    }
    int ans=0;
    for(int j=1;j<=k;j++)
        if(f[n][ans]>f[n][j]) ans=j;
    printf("%d
",f[n][ans]);
    printf("%d",ans);
    get(n,ans);
}
int main(){
    freopen("crew.in","r",stdin);
    freopen("crew.out","w",stdout);
    scanf("%d%d",&n,&k);
    scanf("%s",str+1);
    dp();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/jian-song/p/11587204.html