zoukankan      html  css  js  c++  java
  • CDOJ1693 谁来受罚 [dp]

    题目地址:http://acm.uestc.edu.cn/problem.php?pid=1693&cid=167

      dp[i][j]表示前i点加入j个好人收到的最小代价。

      dp[i][j] = min( 第i点不加入好人的代价, 第i点加个好人的代价 );

      其中

          第i点不加好人的代价 t1 = dp[i-1][j] + ((i-j)==1 && i%10==0)?1:0;

          第i点加好人的代价    t2 = dp[i-1][j-1] + i%10==0?1:0;

    转移时注意某种转移能否进行哟~

    然后在选择最小的之后,记录是由i-1个位子哪个j转移来的。最后从后往前找直接可以得解。

    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #define sf scanf
    #define pf printf
    #define pfn printf("\n");
    #define ll long long
    #define INF 0x7fffffff
    using namespace std;
    struct { int c,j; } dp[10051][51];
    int n,k,a[10001],stack[100],top,ans;
    void ini() { for(int i=1; i<=n+k; i++) for(int j=0; j<=k; j++) dp[i][j].c=INF;}
    void DP(){
        int i,j,t1,t2;
        dp[1][0].c=0;
        dp[1][1].c=0;
        for(i=2; i<=n+k; i++){
            for(j=0; j<=k; j++){
                if(j>i) break;
                if(dp[i-1][j].c!=EOF){
                    if(i%10==0 && a[i-j]==1) t1 = dp[i-1][j].c+1;
                    else t1 = dp[i-1][j].c;
                }
                else t1 = INF;
                if(j>0){
                    if(i%10==0) t2 = dp[i-1][j-1].c+1;
                    else t2 = dp[i-1][j-1].c;
                }
                else t2=INF;
                if(t1<=t2){
                    dp[i][j].c=t1; dp[i][j].j=j;
                }
                else{
                    dp[i][j].c=t2; dp[i][j].j=j-1;
                }
            }
        }
    }
    void print(int i,int j){
        top=0;
        while(i>1){
            if(dp[i][j].j!=j) stack[top++]=i;
            j=dp[i][j].j;
            i--;
        }
        if(j==1) stack[top++]=1;
        cout<<top;
        while(top>0) pf(" %d",stack[--top]);
    }
    int main()
    {
        int ii,jj;
        char s[10],ch;
       while(sf("%d %d",&n,&k)!=EOF){
        gets(s);
        for(int i=1; i<=n; i++){
            scanf("%c",&ch);
            if(ch=='0') a[i]=0;
            else a[i]=1;
        }
        ini();
        DP();
        ans=INF;
        for(int i=n; i<=n+k; i++)
            for(int j=0; j<=k; j++) { if(i-j==n && dp[i][j].c<ans) { ans=dp[i][j].c; ii=i; jj=j;}}
        pf("%d\n",ans);
        print(ii,jj);
        pfn
       }
        return 0;
    }
  • 相关阅读:
    .Net Core 第三方工具包整理
    .Net Core 读取appsettings.json的配置
    .Net Core 常见问题整理
    .Net Core 学习资料
    LVM使用
    PIP本地源搭建
    sed命令使用
    Shell脚本
    SNAT端口转发配置
    Ubuntu软件包管理
  • 原文地址:https://www.cnblogs.com/Lattexiaoyu/p/2550954.html
Copyright © 2011-2022 走看看