A. 2048 Game(思维)
-
题意: 2048游戏,有玩过的都懂。给你一列数字,都是2的次幂,这个数列中相同的数可以互相相加,相加之后两个加数去掉,把和放入数列。之后数列中相同的数字又可以相加。问这个数列在变换中有没有可能出现2048。
-
思路: 比赛时想复杂了,两层循环实现,具体看代码吧,仅供参考!看了大佬的思路和代码才发现这题可以写得很简单。因为所有数都是 2 的次幂且 1+2+4…+1024 全部都只有一个,也只有2047,所以只要确保小于等于2048的数字相加后能大于等于2048即可。
Code1: 比赛时的代码,把所有情况考虑了一遍,代码看起来可能有点复杂。
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
ll a[105];
int main(){
int t; cin>>t;
while(t--){
int n; cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n);
int vis=0;
int flag=1;
for(int i=1;i<=n;i++){
ll sum=a[i];
if(a[i]==2048){
vis=1;
break;
}
for(int j=i+1;j<=n;j++){
if(a[j]<2048){
sum+=a[j];
if(sum==2048){
vis=1;
break;
}
else if(sum>2048) break;
}
else if(a[j]>2048){
flag=0;
break;
}
else{
vis=1;
break;
}
}
if(vis) break;
if(!flag) break;
}
if(!flag){
cout<<"NO"<<endl;
continue;
}
if(vis) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
Code2:
#include <iostream>
using namespace std;
int main(){
int q; cin>>q;
while(q--){
int n; cin>>n;
int sum=0,x;
for(int i=1;i<=n;i++){
cin>>x;
if(x<=2048) sum+=x;
}
if(sum>=2048) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
B. Knights(构造)
-
题意: 要在一个n*n的棋盘中放满黑方和白方的马,马走 ‘日’ 字,求出最优方案使得双方所有马的攻击次数最多。
-
思路: 奇数行奇数列和偶数行偶数列放白马,其他放黑马。
Code:
#include <iostream>
using namespace std;
int main(){
int n; cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if((i%2==1&&j%2==1) || (i%2==0&&j%2==0))
cout<<'W';
else
cout<<'B';
}
cout<<endl;
}
return 0;
}
C. Perfect Team(模拟)
-
题意: a,b,c 三种人各 c,m,x 个,要求 3 人一队且每队必须至少有 a,b 各一个,问最多能组成多少队。
-
思路: 因为 c,m 至少要有一个,所以取 c,m 较小值,然后乘以 3 与 c,m,x 三数之和比较。如果比总数大,说明 c,m 是充足的,所以只需要输出总数除以 3 的结果即可;如果小于等于总数,说明总数是充足的,所以只需输出 c,m 较小值乘以 3 的结果。
Code:
#include <iostream>
using namespace std;
typedef long long ll;
int main(){
int q; cin>>q;
while(q--){
ll c,m,x;
cin>>c>>m>>x;
ll minn=min(c,m);
if(c+m+x>=3*minn)
cout<<minn<<endl;
else
cout<<(c+m+x)/3<<endl;
}
return 0;
}
D. Make The Fence Great Again(二维dp)
-
题意: 给你 n 个格子的高度和提高该格子一个单位高度所需花费的价格,每个格子最多提高两点高度,问使得所有相邻格子不同高度时所需的最小花费。
-
思路: 用二维数组 dp[i][j] 表示格子提高相应的高度所需的花费,j 有三种状态,分别为 0,1,2,然后三层循环遍历,不断地寻找相邻格子高度不相同时三种状态所需的最小花费,最后输出三种状态高度不相同时的最小花费。要注意的就是最后输出的时候要取消同步,否则会TLE。
Code:
#include <iostream>
using namespace std;
typedef long long ll;
const ll inf=2e18;
const int N=3e5+10;
ll dp[N][3],a[N],b[N];
int main(){
ios::sync_with_stdio(0); //要取消同步才不会TLE
int t; cin>>t;
while(t--){
int n; cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i];
dp[i][0]=dp[i][1]=dp[i][2]=inf;
}
dp[1][0]=0; //第一个格子
dp[1][1]=b[1];
dp[1][2]=2*b[1];
for(int i=2;i<=n;i++){
for(int j=0;j<3;j++){
for(int k=0;k<3;k++){
if(a[i-1]+j!=a[i]+k) //如果相邻格子高度不相同
dp[i][k]=min(dp[i][k],dp[i-1][j]+k*b[i]); //取花费小的
}
}
}
//取三种状态花费最小的
cout<<min(dp[n][0],min(dp[n][1],dp[n][2]))<<endl;
}
return 0;
}