noip前的dp挣扎

写了几道比较水的dp,但是也有很多问题,初始化和循环的顺序等问题、还有最大的问题:动规方程。。。

CODEVS1253 超级市场

题目描述 Description

某人喜欢按照自己的规则去市场买菜,他每天都列一个买菜的清单,自由市场的菜码放也有一个顺序,该人有一个特点,就是按顺序买菜,从不走回头路,当然,她希望能花最好的钱买到所有的菜,你能帮帮他吗?

输入输出数据如下图:

思路:比较简单的dp,f[i][j]表示市场上的菜单到i需购买的菜单到j所需的最少花费,若i=j,则更新这个点,否则f[i][j]=f[i-1][j]。初始化将f[i][0]=0;其他都付最大值,最后比较f[n][m]和0x7fffffff,若大于则是impossible,否则输出。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct use{
    int kind;
    double mon;
}b[100001];
double f[100001][101]={0};
int a[101]={0};
int main()
{
    int i,j,n,m,k;
    scanf("%d%d",&m,&n);
    memset(f,127,sizeof(f));
    for (i=1;i<=m;++i)
      scanf("%d",&a[i]);
    for (i=1;i<=n;++i)
      scanf("%d%lf",&b[i].kind,&b[i].mon);
    for(i=1;i<=n;++i)
      f[i][0]=0;
    for (i=1;i<=n;++i)
      for (j=1;j<=m;++j)
      {
          f[i][j]=f[i-1][j];
        if (b[i].kind==a[j])
            f[i][j]=min(f[i][j],f[i-1][j-1]+b[i].mon);
      }
    if (f[n][m]>0x7fffffff) printf("Impossible\n");
    else
      printf("%.2f\n",f[n][m]);
}

RZUC Code

CODEVS1959 拔河游戏

题目描述 Description

一个学校举行拔河比赛,所有的人被分成了两组,每个人必须(且只能够)在其中的一组,要求两个组的人数相差不能超过1,且两个组内的所有人体重加起来尽可能地接近。

思路:一个二维费用(bool)背包问题,一个是元素个数(相当于体积),一个是体重。先求出总重的一半和元素个数一半,进行背包。

#include<iostream>
#include<cstdio>
using namespace std;
bool f[101][45001]={false};
int a[101]={0};
int main()
{
    int i,j,sum=0,n,k,q,cha,summ;
    cin>>n;
    if (n%2==0) k=n/2;
    else k=n/2+1;
    for (i=1;i<=n;++i)
    {
      cin>>a[i];
      sum+=a[i];
    }
    if (summ%2==0) summ=sum/2;
    else summ=sum/2+1;
    for (i=0;i<=1;++i)
      f[i][0]=true;
    for (i=1;i<=n;++i)
      for (j=summ;j>=a[i];--j)
        for (q=k;q>=1;--q)
        f[q][j]=f[q][j]||f[q-1][j-a[i]];
    for (j=summ;j>=0;--j)
      if (f[k][j])
      {
          cout<<min(j,sum-j)<<" "<<max(j,sum-j)<<endl;
        break;
      }
}

RZUC Code

CODEVS1060 搞笑世界杯

题目描述 Description

随着世界杯小组赛的结束,法国,阿根廷等世界强队都纷纷被淘汰,让人心痛不已. 于是有

人组织了一场搞笑世界杯,将这些被淘汰的强队重新组织起来和世界杯一同比赛.你和你的朋

友欣然去购买球票.不过搞笑世界杯的球票出售方式也很特别,它们只准备了两种球票.A 类

票------免费球票 B 类票-------双倍价钱球票.购买时由工作人员通过掷硬币决定,投到正面

的买A类票, 反面的买B类票.并且由于是市场经济,主办方不可能倒贴钱,所以他们总是准备

了同样多的A类票和B类票.你和你的朋友十分幸运的排到了某场精彩比赛的最后两个位置.

这时工作人员开始通过硬币售票.不过更为幸运的是当工作人员到你们面前时他发现已无需

再掷硬币了,因为剩下的这两张票全是免费票。

你和你的朋友在欣喜之余,想计算一下排在队尾的两个人同时拿到一种票的概率是多少

(包括同时拿A 类票或B类票) 假设工作人员准备了2n 张球票,其中n 张A类票,n 张B类票,并且排在队伍中的人每人必须且只能买一张球票(不管掷到的是该买A 还是该买B).

思路:先说一个比较坑爹的事情,读入的是2n,不是n。f[i][j]表示第i人买票时买了j张A票的概率。对于j有三种情况:

1)j=0:f[i][j]=f[i-1][j]*0.5;   2)0<j<n:f[i][j]=(f[i-1][j]+f[i-1][j-1])*0.5;  3)j=n:f[i][j]=f[i-1][j]+f[i-1][j-1]*0.5。

初始化f[0][0]=1;输出f[n*2-2][n]*2(因为最后两张可以全是A或B);

#include<iostream>
#include<cstdio>
using namespace std;
double f[3000][3000]={0};
int main()
{
    int n,i,j;
    cin>>n;
    n/=2;
    f[0][0]=1;
    for (i=1;i<=2*n;++i)
      for (j=0;j<=n;++j)
      {
          if (j>i) continue;
          if (j==0) f[i][j]=f[i-1][j]*0.5;
          else
          {
              if (j<n) f[i][j]=(f[i-1][j]+f[i-1][j-1])*0.5;
              else f[i][j]=f[i-1][j]+f[i-1][j-1]*0.5;
          }
      }
    printf("%.4f\n",f[n*2-2][n]*2);
}

RZUC Code

CODEVS3369 膜拜

题目描述 Description

神牛有很多…当然…每个同学都有自己衷心膜拜的神牛.
某学校有两位神牛,神牛甲和神牛乙。新入学的N位同学们早已耳闻他们的神话。所以,已经衷心地膜拜其中一位了。
现在,老师要给他们分机房。
但是,要么保证整个机房都是同一位神牛的膜拜者,或者两个神牛的膜拜者人数差不超过M。
另外,现在N位同学排成一排,老师只会把连续一段的同学分进一个机房。老师想知道,至少需要多少个机房。

思路:预处理一下前i位置有多少个两个神牛的崇拜者(前缀和数组),然后就是dp部分了,f[i]表示分到i个人最少多少个教室,循环i和k(i-k表示最后一个教室的人数),更新f[i]的值。预处理:f[0]=0;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int f[3000]={0},sum1[3000]={0},sum2[3000]={0};
int main()
{
    int n,m,i,j,x;
    memset(f,127/3,sizeof(f));
    scanf("%d%d",&n,&m);
    for (i=1;i<=n;++i)
    {
      sum1[i]=sum1[i-1];
      sum2[i]=sum2[i-1];
      scanf("%d",&x);
      if (x==1) ++sum1[i];
      else ++sum2[i];
    }
    f[0]=0;
    for (i=1;i<=n;++i)
      for (j=0;j<i;++j)
        if (abs((sum1[i]-sum1[j])-(sum2[i]-sum2[j]))<=m||
           sum1[i]-sum1[j]==0||sum2[i]-sum2[j]==0)
          f[i]=min(f[i],f[j]+1);
    cout<<f[n]<<endl;
}

RZUC Code

CODEVS

题目描述 Description

现在有n个物品(有可能相同),请您编程计算从中取k个有多少种不同的取法。

思路:多重背包问题,将数字作为元素,出现的次数为个数。注意选取个数时候的循环要循环到1,一开始循环到了0,结果wa了。。。作死。。。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[31],f[31]={0},w[31]={0};
int main()
{
    int n,k,i,j,p;
    cin>>n>>k;
    for (i=1;i<=n;++i)
      cin>>a[i];
    sort(a+1,a+n+1);
    ++w[0];
    ++w[w[0]];
    for (i=2;i<=n;++i)
    {
      if (a[i]==a[i-1])
        ++w[w[0]];
      else
      {
          ++w[0];
          ++w[w[0]];
      }
      if (w[w[0]]>k) w[w[0]]=k;
    }
    f[0]=1;
    for (i=1;i<=w[0];++i)
      for (j=k;j>=0;--j)
        for (p=w[i];p>=1;--p)
          if (j>=p)
            f[j]=f[j]+f[j-p];
    cout<<f[k]<<endl;
}

RZUC Code

时间: 2024-10-14 23:09:02

noip前的dp挣扎的相关文章

NOIP前必须记住的30句话

NOIP前必须记住的30句话 1.比赛前一天晚上请准备好你的各种证件,事先查好去往考场的路线2.比赛之前请先调整你的屏幕分辨率到你喜欢的大小3.比赛之前请把编译器的字体调为你平时惯用的字体,尤其是注意这种字体中的逗号,点,1,l这种易混淆的字是不是区分明显4.在不影响视野的情况下,请将字号尽可能调大,方便查错5.请将题目通读完以后,再开始深入思考你认为最容易的一道题6.即使这道题再容易,也不要着急写代码,请先明确自己每一步要干什么后,再开始写,轻敌会是你最大的错误7.即使这道题看起来再没法做,也

Noip前的大抱佛脚----文章索引

Noip前的大抱佛脚----赛前任务 Noip前的大抱佛脚----考场配置 Noip前的大抱佛脚----数论 Noip前的大抱佛脚----图论 Noip前的大抱佛脚----动态规划 Noip前的大抱佛脚----数据结构 Noip前的大抱佛脚----根号对数算法 Noip前的大抱佛脚----字符串 Noip前的大抱佛脚----一些思路 Noip前的大抱佛脚----奇技淫巧 原文地址:https://www.cnblogs.com/xzyxzy/p/9903933.html

$Noip$前的小总结哦

考试失误点与积累 有点不知道该干嘛了,状态有点差,写点东西.(后面可能会加更一点东西?) 常规错误 \(1.\) 数组开小 \(2.\) \(int\)和\(longlong\) \(3.\) 开某题时间太久 \(4.\) 某题调不出来强行放弃心态爆炸 \(5.\) 被卡无限栈(???) \(6.\) 不重视考场最后的挣扎,痛失高分 \(7.\) 注释有用代码块 \(8.\) 在对拍外面改掉的错误,对拍里没改,交上去了对拍里面的代码 \(9.\) \(freopen\)里面的\('.'\)打成\

Noip前的大抱佛脚----根号对数算法

根号算法 分块 数列分块入门九题(hzwer) 入门题1,2,3,4,5,7 问题:给一段区间打上标记后单点查询 解法:主要是每块维护一些标记,计算答案等,此类分块较为简单 注意:块大小一般为\(\sqrt n\) 复杂度:\(O(n\sqrt n)\) 入门题6 问题:每次朝数列中间插入一个元素,查询第k个元素是什么 解法:块大小超过一定值后暴力重构!采用链表实现 复杂度:\(O(n\sqrt n)\) 入门题8 问题:每次询问一个区间内为\(c?\)的元素个数,并把整个区间改为\(c?\)

[noip模拟]散步&lt;dp&gt;

题目链接:http://begin.lydsy.com/JudgeOnline/problem.php?id=2097 这题A的时候,百感交集五味杂陈............ 就这么一道看起来简单的不得了的裸的一件内衣都不剩的dp我就卡了几天 唉,看来我这种蒟蒻是没有救了. 看完题后,有些朋友可能会和我一样去定义一个数组f[i,j,l,r]表示第一个人在i,j位置,第二个人在l,r位置 然后一看n是小于等于100就放心大胆的继续码代码下去了 但实际上这东西如果单纯循环不仅仅会爆时间,还要爆内存(

NOIP前刷水行动

2016.11.10 BZOJ1592 Usaco2008 Feb]Making the Grade 路面修整:离散+DP BZOJ1051 HAOI 受欢迎的牛 :tarjan BZOJ2442 修建草坪 :单调队列优化DP BZOJ3890 Meeting time : 分层DP BZOJ4390 Max Flow :树上差分 BZOJ4525 :二分答案判定 BZOJ4511 :DP 1 BZOJ1592 2 3 #include<iostream> 4 #include<algo

【写在NOIP前】

快NOIP了,感觉自己得总结一下吧. 1.要自信啊,相信自己啊,我明明还是有些实力的是吧. 哪怕之前被教练怎么怼,自己别放弃啊 一定要注意心态吧,考试的时候怎么都不能慌,你不会的题也不会有多少人会做的,你觉得难写的题别人也不好写啊 2.注意细节 作为日常挂细节选手一定要注意,多读题多读代码,多测试边界情况. 读题多注意,把关键词和易错点先列好,反正就是宁可写慢点,也别写挂了. 把能想到的分都拿稳就已经很稳了对吧 3.模拟赛 总结点模拟赛经验教训啥的,回头仍在错误汇总里面吧,NOIP之前多看看..

Noip前的大抱佛脚----一些思路

一些有启发性的思路 序列 线段树(当然还要有主席树啊!) 差分和前缀和啊 分块 莫队 看到等差数列先推一波式子啊(天天爱跑步) 有序序列的动态插入删除 有的时候需要算贡献,当你发现序列(离散化后)值域一定时,便可以尝试使用树状数组 维护\(mex\) 可以尝试使用值域分块,当这个块内全部有值了就打个\(tag\) 等和序列 大概就是说可以多项式乘起来那种吧,可以发现差分之后是回文串! 序列差分 异或序列可以差分!!(具体差分方法:遇到一个1,给当前位置和下一个位置异或上一个1,这样统计前缀和后就

Noip前的大抱佛脚----数论

数论 知识点 Exgcd \(O(logn)\)求解\(Ax+By=C\)的问题 1.若\(C\%gcd(A,B)!=0\)则无解 2.\(Gcd=gcd(A,B);A/=Gcd,B/=Gcd,C/=Gcd\) 3.代入下面代码求\(Ax+By=1\) 4.\(x*C\),得到一组特解 5.通解为\(\begin{cases}x=x_0+k*B \\y=y_0+k*A\end{cases}\) void Exgcd(ll a,ll b,ll &x,ll &y) { if(!b){x=1;y