周总结

周总结

Vjudge题目总结
题目网址:https://vjudge.net/contest/426531
M.
这个题读懂题意更重要
错误题意1.
错把66为底箱子当成都是666的箱子
错误题意2.
错把箱子为1
1 22 33…的高度看成与底边边长相等
真●题意:箱子的高度其实可以直接忽略,因为一个箱子里面的高度全都相等,这个题意就是用来挖坑的,坏的很,读懂题意的话,就可以直接转化为平面问题——切木板问题,一个66的木板,切所需数量nn的木板,最少用多少个66的木板,题意读懂,整个题思路的困难就迎刃而解
思路:按照从小到大,依次切木板,求最少需要6
6木板的数量,66 55 44每一个要切的木板都需要一个66的木板来操作,而33的木板4个需要1个66的木板,这里根据计算机除法运算的规律,用33的数量+3之后除以4,得到33所用的66木板数,然后计算出66木板所剩的22木板的空位,填入22木板后,多了加木板,然后计算所剩1*1可切木板数,少了直接计算数目,最后输出结果
P.
题意:这个题最重要的就是题意部分,看着很长很复杂,可能会写很多代码,其实总结一遍题意,最后可以直接等价为求n个人里面最先到达终点的人所用的时间
思路:一开始没有读透题意,写了一堆代码

while(l<4500)
    {
        t=(p[j+1].t-p[j].t)*p[j+1].v/(p[j+1].v-p[j].v);
        for(i=j+2;i<n;i++)
        {
            temp_t=(p[i].t-p[j].t)*p[i].v/(p[i].v-p[j].v);
            if(temp_t<t)
                {t=temp_t;j=i;}
        }
        if(temp_v*t<4500)
        {sum+=t;
        l+=temp_v*t;}
        else
        {
            t=(4500-l)/temp_v;
            sum+=t;
            l=4500;
        }
        temp_v=p[j].v;
        j++;
        if(j==n-1)
        {sum+=(4500-l)/temp_v;l=4500;}
    }//看似逻辑清晰,结果也没错,可就是没AC

其实根本不用这么麻烦,直接求最快到达的时间,然后输出
在AC之后,我发现了一个非常有意思的事情,这个是AC的代码:

#include <iostream>
#include <algorithm>
#include <iomanip>
using namespace std;
struct tim
{
    int v,t;
    double ti;
}p[10005];
bool cmp(tim a,tim b)
{
    return a.ti<b.ti;
}
int main()
{
    int n,i,j,sum;
    while(cin>>n&&n!=0)
    {
        for(i=0;i<n;i++)
        {
            cin>>p[i].v>>p[i].t;
            p[i].ti=p[i].t+4.5/p[i].v*3600;
        }
        sort(p,p+n,cmp);
        for(i=0;i<n;i++)
              if(p[i].t>=0)
	break;
        sum=p[i].ti;
        if(sum!=p[i].ti)
            sum++;
        cout<<sum<<endl;
    }
    return 0;
}

我只修改了一个地方

for(i=0;i<n;i++)
        {
            cin>>p[i].v>>p[i].t;
            p[i].ti=p[i].t+4.5/p[i].v*3600;//修改为 p[i].ti=p[i].t+4500/p[i].v*3.6;或者改为p[i].ti=p[i].t+4500/(p[i].v/3.6);
        }

如果进行修改,则是wrong answer这让我感觉有点摸不着头脑,如果站在数学的思路看问题,完全没有错误,但为什么在机器上这三个式子却不成立,为了搞明白怎么回事,我把sum设置为double类型,把代码

if(sum!=p[i].ti)
            sum++;

去掉,然后输入同样的例子
2
21 0
22 34
AC的代码p[i].ti=p[i].t+4.5/p[i].v3600;输出的结果是770.364
改为p[i].ti=p[i].t+4500/p[i].v
3.6;输出的结果是768.4
改为p[i].ti=p[i].t+4500/(p[i].v/3.6);输出的结果是770.364
显然,第一个修改后连输出结果都出现了错误
但是第二个修改之后结果并没有错误,但提交之后仍然是wrong answer
为什么?
等号左边p[i]ti,这是double类型,p[i].t是int整形
先看AC代码,p[i].ti=p[i].t+4.5/p[i].v3600;根据优先级,先左后右,小数除以整型变量,没有问题,然后小数乘以整数,得小数也没有问题
再看修改的第一个代码,p[i].ti=p[i].t+4500/p[i].v
3.6;根据优先级先左后右,第一个修改后先除法4500/p[i].v就出现了错误,整形除整形,如果结果不是整数,那么就会出现精度的缺失,后面整型乘3.6没有问题
再看第二个修改的代码,p[i].ti=p[i].t+4500/(p[i].v/3.6);括号内整数除以小数,括号外仍然是整数除以小数,为了防止巧合,我又写了一段代码

int main()
{
    double p;
    p=4+28/3.6;
    cout<<p;
    return 0;
}

结果仍然没有出现精度缺失,那么就只剩下一种情况,就是想AC就不能出现整数除以小数的形式,但是小数可以除以整数
W.
思路:首先这个题应该弄清楚先算最少时间还是先算最少次数,如果像题中说的一样,最少时间的时候的最少次数,可能会先想办法把最少时间求出来,但是这样反倒不好求,如果先求最少次数,然后可以直接顺水推舟求出来最少时间,最少次数即总车数除以一次可以运送的车数,即可得到总共需要的最少次数,如果该除数有余数则先运送余数,并输入最先运送的车到达的时间,现在所用的最少时间即最大时间加2t,然后再输入剩下的车辆到达时间,在输入的汽车数可以装满一整船(即达到n时)进行时间判断,如果时间未达到上次船回到码头的时间,最少时间直接+2t,否则按照到达时间的最大值作为托运开始时间进行托运,运送完最后一批车时,时间减速一个t即得到最少花费时间
这个题其实并不算难,但为什么让很多人望而却步?简单分析一下,就是对于判断模棱两可,不知道判断标准,就像为什么在不能整除时要先运余数而不是后运余数,其实只要一组数据就可以说明
2 10 3
10
40
40
在等待可以满载的时候其实就是在浪费时间
还有就是涉及的变量太多,如果一次性定义所有产量难免会产生一些看不出来的小错误,解决办法就是在需要变量时再进行定义,同时在循环结束时也减少了变量值的重置

#include <iostream>
using namespace std;
int main() 
{
 int k;
cin>>k;
int n,t,m;
while(k--)
{
	cin>>n>>t>>m;
	int a=m%n;
	int times=m/n;
	if(a!=0)
		times++;
	int minTime=0,ship,i=0;
	if(a)
 {
		for(i=0;i<a;i++)
			cin>>ship;
		minTime=ship+2*t;
	 }
	int ans=0;
	while(i<m)
{
		cin>>ship;
		ans++;
		if(ans==n)
  {
			if(ship>minTime)
      minTime=ship+2*t;
  else minTime+=2*t;
	ans=0;
			}
		i++;
		}
	minTime-=t;
	cout<<minTime<<" "<<times<<endl;
	}
	return 0;
} 

课上题目:
直线上有n个城市, 第i个城市和i+1个城市是相邻的. 每个城市都有vi的金币.
Alice和Bob站在城市p, 他们每天可以选择走向一个相邻的城市, 也可以选择不走. 他们是单独行动的.
他们经过一个城市就可以获得相应的金币(不能重复获得)
作为一个队伍, 他们的最远距离不能超过M, 问T天内, 他们最多一共能拿多少金币?

思路:其实如果T一直大于M/2的话,这个题就非常简单,同时相对而行,直到距离达到M,所用天数为d,然后在接下来T-d天内哪里金币多往哪里走,如果天数到了,还没有达到M,直接所有城市的金币相加啊,更简单,所以不需要判断语句,但是要判断M的奇偶性,偶数很简单,主要是奇数,仔细一想奇数也很好判断,但是需要的if判断语句好像有点多,在M较大时,需要判断需要哪边走的天数为偶数,然后再判断再往哪边走可以得到最大值,我感觉直接列举,因为奇数也只有四种情况,得到四种情况的最大值,输出。
3.25CF
题目A
A题目其实非常非常简单,就像是初中水平数学的一道益智题,或者是高中数学里面一道5分的选择或者填空题,但是为什么花费了这么长时间,还出现了这么多次错误?
1:没有做到简化题目,对题目理解不够,对题目分析不到位,就像高中老师常给我们说的一句话:“你要明白出题人的目的,出题人想考察你什么”,我在看到题目的时候第一个想到的不是找规律,而是去定义二维数组使用for循环。
2:受贪心思想和Vjudge上题目的影响,不会想到这一题直接两个加减乘除的式子就可以解决,最后还是在敲代码的时候发现,二维数组根本用不到,用for循环做出来之后提交发现超时,这才想到用一个if语句和两个加减乘除的式子解决该问题
题目B
当时太着急了,以至于心急没吃到热豆腐
思路还是有的,不过当时没写出来:
在输入字符的时候进行判断,在p[i]==星号 时记录i的位置,到最后的位置记录就是最后一个符号的位置,并令其等于’.’,然后使用for循环,记录下temp=第一个的位置同样使其等于’.’,同时数量+1使用for循环,如果i-temp<=3&&p[i]==星号 跳过,否则的话temp=当前位置,然后p[temp]=’.’,变换的数量+1;
最后输出
感想:
还是感觉老毛病,思路还没清晰,就开始敲代码,浪费时间浪费心态,应该好好改一下,最近贪心算法的题做的差不多了,初识了动态规划,感觉更难了,感觉到了不小的压力,不过想想还是坚持下去吧,就像养成习惯一样,最开始是因为好奇心驱使或者一时兴起,慢慢的兴趣不再像开始那样,坚持下去也非常困难,但是如果度过了这个困难期,最后的成为了习惯,生活中失去他就变得非常困难了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值