A:投掷骰子
知识点:枚举
思路:使用f数组进行标记f[i] [j]表示红色点数i,黑色点数j的方案是否可行。
那么就可以枚举第一个第二个第三个筛子的点数,然后计算对应的红点分数和黑点分数进行标记。最后再逐个询问输出即可。
参考代码:
#include<bits/stdc++.h>
using namespace std;
int n,x,y,f[101][101];
int r[]= {0,1,0,0,4,0,0};
int b[]= {0,0,2,3,0,5,6};
int main() {
for(int i=1; i<=6; i++) //掷色子1
for(int j=1; j<=6; j++) //掷色子2
for(int k=1; k<=6; k++) { //掷色子3
int x=r[i]+r[j]+r[k];
int y=b[i]+b[j]+b[k];
f[x][y]=1; //枚举所有的可能结果
}
cin>>n;
while(n--) {
scanf("%d%d",&x,&y);
if(f[x][y])printf("YES\n");
else printf("NO\n");
}
return 0;
}
B:伙伴
知识点:数组模拟
思路:使用数组来模拟左边伙伴和右边伙伴,需要注意两边的处理。
若删除了x这个士兵,则x这个士兵左侧的那个士兵的右边士兵为r[x];
则x这个士兵右侧的那个士兵的左边士兵为l[x]。
参考代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,x,l[1000001],r[1000001];
int main() {
cin>>n>>m;
for(int i=1; i<=n; i++)
l[i]=i-1,r[i]=i+1;
for(int i=1; i<=m; i++) {
cin>>x;
if(l[x]==0) printf("* %d\n",r[x]);
else if(r[x]==n+1) printf("%d *\n",l[x]);
else printf("%d %d\n",l[x],r[x]);
r[l[x]]=r[x];
l[r[x]]=l[x];
}
return 0;
}
C:手机充电
知识点:递归
思路:对于每次电量n进行判断,若电量大于50%,则让手机处于不充电的状态,电量减少3%,若电量小于50%,则让手机处于充电状态,电量加上2%,若是电量等于50%,则直接可以返回,整个递归过程的结果可以保存在f[]数组里面,让每次遇到电量为n时不再重复计算,节省递归时间。
代码:
#include<bits/stdc++.h>
using namespace std;
int t,n,f[101];
//手机电量到达50%的最短时间
int dfs(int n,int t) {
if(f[n]) return f[n];
if(n>50) f[n]=dfs(n-3,t+1);
if(n<50) f[n]=dfs(n+2,t+1);
if(n==50) f[n]=t;
return f[n];
}
int main() {
cin>>t;
while(t--) {
cin>>n;
memset(f,0,sizeof(f));
cout<<dfs(n,0)<<endl;
}
return 0;
}
D:切割钻石
知识点:动态规划、完全背包
思路:钻石可以切割为任意大小不等,所以可以使用dp[j]表示钻石重量为j时的最大收益,那么不考虑切割成重量为i的钻石为dp[j],考虑切割成重量为i的钻石为dp[j-i]+a[i],那么取二者最小值即可。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,a[2001],dp[2001];
//dp[j]:重量为j的最高价格为dp[j]
int main() {
cin>>n;
for(int i=1; i<=n; i++) {
cin>>a[i];
}
for(int i=1; i<=n; i++) {
for(int j=i; j<=n; j++) {
dp[j]=max(dp[j],dp[j-i]+a[i]);
}
}
cout<<dp[n];
return 0;
}