记录不会做的题,贴代码,写题解
vj贪心专题链接
Packets cf1037A
题意:
有一堆横截面为1×1, 2×2, 3 × 3, 4 × 4, 5 × 5, 6 × 6的物品,问至少需要多少个横截面为6×6的盒子才能装下?(盒子和物品高度相同);多组输入。
基本思路:
先装大的,再用小的填充。贪心思维体现在:尽量装满每个盒子。
就是简单模拟,运用贪心思想,把基本需求列出来就好了。主要是细心。看看别人的博客,有人的ac代码很短,我也学习学习。
一开始错了一个很简单的地方。。WA了好久,难受。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <string.h>
#include <map>
#include <stdlib.h>
#define MAX_N 1e8+7
#define ll long long
using namespace std;
int main()
{
int a[10];
while(scanf("%d%d%d%d%d%d",&a[1],&a[2],&a[3],&a[4],&a[5],&a[6])!=EOF)
{
if(a[1]==0 && a[2]==0 && a[3]==0 && a[4]==0 && a[5]==0 && a[6]==0)
break;
ll ans=0;
//先装大的,再装小的
ans+=a[6];
ans+=a[5];
//5+1
a[1]-=a[5]*11;
ans+=a[4];
ll left4=a[4]*20;
//4+2+1
if(a[2]<a[4]*5)
{
left4-=a[2]*4;
a[2]=0;
}
else
{
a[2]-=a[4]*5;
left4=0;
}
a[1]-=left4;
//3+2+1
ans+=a[3]/4;
ll leftof3=a[3]%4;
if(leftof3==1)
{
ll left3=27;
ans++;
if(a[2]>=5)
{
a[2]-=5;
left3=7;
}
else
{
left3-=a[2]*4;
a[2]=0;
}
a[1]-=left3;
}
if(leftof3==2)
{
int left3=18;
ans++;
if(a[2]>=3)
{
a[2]-=3;
left3=6;
}
else
{
left3-=a[2]*4;
a[2]=0;
}
a[1]-=left3;
}
if(leftof3==3)
{
int left3=9;
ans++;
if(a[2]>=1)
{
a[2]-=1;
left3=5;
}
a[1]-=left3;
}
//2+1
int left2=0;
if(a[2]>0)
{
if(a[2]%9!=0){
ans+=a[2]/9+1;
left2=36-(a[2]%9)*4;
}
else{
ans+=a[2]/9;
}
}
//最后剩下的1
if(a[1]>0)
{
a[1]-=left2;
if(a[1]>0){
if(a[1]%36!=0){
ans+=a[1]/36+1;
}
else{
ans+=a[1]/36;
}
}
}
cout<<ans<<endl;
}
}
以上是我的ac代码,顺着思路写的,很长很麻烦。。。
一会学习一下别人的好代码。
————————————
————————————
WOW Factor cf1178B
题意:
按照上述规则,寻找字符串中有多少个“WOW”
基本思路:
对每个‘o’分析在前/后共有多少个符合要求的’w’
代码:
char a[1000007];
ll cntwl[1000007];
ll cntwf[1000007];
int main()
{
scanf("%s",a);
int n=(int)strlen(a);
ll sum=0;
ll cnto=0;
for(int i=0;i<n;i++){
if(a[i]=='o')
cnto++;
}
ll l=0;
ll cntoo;
cntoo=0;
for(int i=0;i<n;i++){
if(a[i]=='v'&&a[i-1]=='v'&&i>0){
l++;
}
if(a[i]=='o'){
cntoo++;
cntwl[cntoo]=l;
}
}
ll f=0;
cntoo=cnto;
for(int i=n-1;i>0;i--){
if(a[i]=='v'&&a[i-1]=='v'){
f++;
}
if(a[i]=='o'){
cntwf[cntoo]=f;
cntoo--;
}
}
for(int i=1;i<=cnto;i++){
//cout<<i<<' '<<"cntwl[i]="<<cntwl[i]<<endl;
//cout<<i<<' '<<"cntwf[i]="<<cntwf[i]<<endl;
sum+=cntwl[i]*cntwf[i];
}
cout<<sum<<endl;
}
第一次写,TLE了,因为写法复杂度最高达到n^2。。多次重复计算,知道错了!
第二次思路没有问题,但是在一个细节处WA了,因为没有考虑‘o’在开头的情况
——————————
——————————
一个奇妙的超傻的题让我想思考关于浮点数的问题
cf 1199B
反正就是直接输出方程结果,要求误差小于10e-6
浮点数到底怎么搞啊。。
x用十进制精确表达的数值是8/3,也就是2.6666666666666(循环),这组数据中浮点输出在小数点后15位开始不精确,测试了更多的输出位数,如图
可以得出一点小结论:
double类型浮点数在小数点后十几位开始不精确;
浮点数用printf输出的时候会四舍五入
——————————
——————————
Minimize the Permutation
cf1256B
得到字典序最小的数字,而且限制移动次数,那么就得让每个位置能移动的最小的数向前移。
从后往前遍历,如果前面的比后面的小,交换位置,同时标记交换的坐标,因为每个坐标只能移动一次。这样可以保证小数字尽量向前移,而且不浪费每一个移动的机会;
然后再从前往后遍历一次,因为上一次遍历时,如果前一位小于后一位,那这个坐标的移动机会便没有被使用,而且通过后续操作,上一次较小的数字可能已经往前移动,更新了数据,上一次较大也有可能继续前移。
int main()
{
int t;
cin>>t;
while(t--){
int n;
cin>>n;
int a[107];
int b[107]={0};
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=n-1;i>=1;i--){
if(a[i+1]<a[i] && b[i]==0){
swap(a[i+1],a[i]);
b[i]=1;
}
}
for(int i=1;i<=n-1;i++){
if(a[i+1]<a[i] && b[i]==0){
swap(a[i+1],a[i]);
}
}
for(int i=1;i<=n;i++){
cout<<a[i]<<' ';
}
cout<<endl;
}
}