A - Alice’s Print Service
给出打印张数多个优惠,查询打印的最便宜的方法是什么。
首先对于任意一个打印的张数,都可以被划分成若干个区间,在这一个区间选择多少的打印张数是最便宜的。
因为是优惠和对应的价钱是递增,递减的所以我们将每个优惠的准入条件存一个后缀最小值,对于每个查询,我们在所有的钱的数量中二分一个值,判断一下如果以这个优惠条件买是不是最优的就行,因为后面的优惠可能巨大,这个时候后缀的最小值就起到作用了、
C - Collision
强行用余弦定理搞一发公式算一下就ok,注意精度
J - Josephina and RPG
经典dp,每次只有两个分支,选择上一次击败的对手或者不选择。设dp[i][j]是第i局派出第j个队伍,那么只要先更新dp[i][t[i-1]] ,在更新其他的地方就ok了
K - Pocket Cube
这道题要求再K步之内判断多少个面被还原了。
由于年少的时候练过一点点三阶,没有注意到这样的性质:如果对二阶魔方做R,相当于做了一个L’这样我们可以吧12步操作优化到6步,也就是说最后只有6^7中状态,随便剪剪就过了。
但是同样的放在三阶就不行了,思维僵化不是件好事啊……
最好魔方写成置换,要不然浪费时间
#include <bits/stdc++.h>
#include <bitset>
#define ll long long
#define INF 0x3f3f3f3f
#define pr pair<int,int>
#define fi first
#define next fuck
#define se second
using namespace std;
int a[30];
inline bool _check(int a,int b,int c,int d)
{
return a == b && a == d && a == c;
}
int n;
int ans;
void check()
{
int res = 0;
res += _check(a[0],a[1],a[2],a[3]);
res += _check(a[6],a[7],a[12],a[13]);
res += _check(a[16],a[17],a[18],a[19]);
res += _check(a[20],a[21],a[22],a[23]);
res += _check(a[4],a[5],a[10],a[11]);
res += _check(a[8],a[9],a[14],a[15]);
ans = max(ans,res);
}
const int tra[6][24]={
{2,0,3,1,6,7,8,9,23,22,10,11,12,13,14,15,16,17,18,19,20,21,5,4},
{1,3,0,2,23,22,4,5,6,7,10,11,12,13,14,15,16,17,18,19,20,21,9,8},
{0,1,11,5,4,16,12,6,2,9,10,17,13,7,3,15,14,8,18,19,20,21,22,23},
{0,1,8,14,4,3,7,13,17,9,10,2,6,12,16,15,5,11,18,19,20,21,22,23},
{0,21,2,23,4,5,6,1,9,15,10,11,12,3,8,14,16,7,18,13,20,17,22,19},
{0,7,2,13,4,5,6,17,14,8,10,11,12,19,15,9,16,21,18,23,20,1,22,3}
};
void dfs(int pos)
{
int s[30];
if(ans == 6) return ;
if(pos >= n) return ;
memcpy(s,a,sizeof(a));
for(int k = 0;k<6;k++)
{
memcpy(a,s,sizeof(s));
for(int j = 0;j<24;j++) a[j] = s[tra[k][j]];
check();
dfs(pos+1);
}
return ;
}
int main()
{
while(scanf("%d",&n) != EOF)
{
for(int i = 0;i<24;i++) scanf("%d",a+i);
ans = 0;
check();
dfs(0);
printf("%d\n",ans);
}
return 0;
}
还是好菜啊……