1004 Link with Equilateral Triangle
题意
n个点,组成一个大三角形,中间内嵌n^2个小三角形,左边不可以编号0,右边不可以编号1,下面不可以编号2,并且每个小三角形的编号之和不能是3的倍数,问给定n,能不能把n个顶点都编好号。
思路
猜,找规律,画几个发现根本不可以
代码
cout<<"No"<<endl;
1006 BIT Subway
题意
购买n件物品,有两种计价方式
1. 商品不可拆分付款,一旦满了100元,后面的商品每件八折,一旦再满了200元,后面的商品每件五折。
2.商品可拆分付款,可以把一件商品拆开金额,一部分用去凑满100元,另一部分打8折, 到了200的时候同理,可以将商品拆开,一部分用去填满200元,一部分打5折。
问给定n件商品的价格 两种计价方式各总价多少钱?
思路
第一种计价方式直接设置一个flag,标记当前有没有满100,200,并根据flag用不同折扣。
第二种直接先算总价,然后拆分成3段,第一段内不打折,第二段内8折,第三段内5折。
代码
#include<iostream>
#include<cstdio>
using namespace std;
int n, t;
double a[100005];
int main()
{
scanf("%d", &n);
while(n--)
{
scanf("%d", &t);
double sum1 = 0, sum2 = 0;
int flag2 = 0;
for(int i=0; i<t; i++){
scanf("%lf", &a[i]);
sum1 += a[i];
// 第二种情况
if(flag2 == 0) sum2 += a[i];
if(flag2 == 1) sum2 += 0.8*a[i];
if(flag2 == 2) sum2 += 0.5*a[i];
if(sum2>=100 && sum2<200) flag2 = 1;
if(sum2>=200) flag2 = 2;
}
if(sum1>=100){ //第一种情况直接先全部累加然后特判一下
double cha = sum1 - 100;
if(cha>=125) sum1 = 200 + (cha - 125)*0.5;
else sum1 = 100 + cha*0.8;
}
printf("%.3lf %.3lf\n",sum1,sum2);
}
}
1007 Climb Stairs
题意
从1到n层有n个人物,有不同的伤害值ai,我在第0层,初始伤害值a0,并且我有一个最大可上升层数k,我只能上升k层以内,或者下降一层,但是我不能走到已经走过的层。 当我的伤害值>=某层人物的伤害值时,我可以将它打败并且吸收它的能力值,问最终能不能打败所有人物。
思路
枚举怪物,如果当前我的伤害值大于它的,那么直接把他吃掉,否则就肯定需要跳跃先吃后面的,那么由于我只能下降一层,所以我们在往后跳的过程中,一旦发现吃掉后面某一段后 (在跳跃范围内) 再回来可以吃掉它的话,那就让我跳到这一段的右边界,然后从那里回来,判断能不能成功回来,如果能成功吃回来,当前点遍历点就跳到右边界的下一个点,否则,在遍历点能直接跳到的范围-1 内继续往后跳,然后检查能不能顺利回去遍历点。
假设当前在第二层:不能吃掉2,那就往后检测,【注意检测边界是我的最大步数的前一步,因为我最后吃完了2还要往前跳,又不能跳到已经吃过的点,所以一定要给自己留一条路】 如果发现必须吃掉3 4之后才够吃2, 那就从4开始往回走,依次判断:当前能否吃掉4,如果能吃掉4能不能吃掉3,....依次判断到2; 如果有一个不能的话,就继续往后检测,检测点跳到5 然后检查5->4->3->2是否顺利,如果都不行,就无解。 如果说从后面某个检测点能顺利回来把2吃完后,那么当前点就跳到检测点的下一个点,继续操作。
代码
#include<bits/stdc++.h>
using namespace std;
int n, a0, k, t;
long long a[100010];
long long f[100010]; //前缀和
int main()
{
cin>>t;
while(t--){
cin>>n>>a[0]>>k;
f[0] = a[0];
for(int i = 1; i <= n; i++) {
cin>>a[i];
f[i] = f[i-1] + a[i];
}
long long sum = a[0], tempsum;
int j, F, kk;
F = 1;
for(int i = 1; i <= n; i++)
{
if(sum>=a[i]){ // 如果能吃掉 直接吃
sum += a[i];
continue;
}
if(i==n) { //如果现在已经走到了第n个 又吃不掉 那就不行
F = 0;
break;
}
int endd = i + k - 1; //否则先跳到后面再往前吃
if(endd>=n) endd = n; //如果可以跳到最后一步
int flag = 0; //记录能不能从后面往前成功吃掉i
for(j = i+1; j <= endd; j++) { //遍历能跳到的点
if(f[j] - f[i] + sum >= a[i]){ //如果一旦发现吃完i+1 到j这一段就能吃掉a[i] 那就从j回溯
tempsum = sum;
for(kk = j; kk>=i; kk--){
if(tempsum >= a[kk]) tempsum += a[kk];
else break; //如果发现回到一半回不了了
}
if(kk == i-1) { //如果顺利回去了i
flag = 1;
sum = tempsum;
//cout<<"从"<<j<<"回溯成功到"<<i<<endl;
//cout<<"当前伤害值"<<sum<<endl;
i = j;
break; //表示当前j可以 不用继续往后找j了
}
}
}
if(!flag) {
F = 0;
break;
}
}
if(F) puts("YES");
else puts("NO");
}
return 0;
}