B:「金」点石成金
题面:
思路:注意到n范围很小直接暴力。
dfs暴力枚举每个物品选和不选产生的影响,注意当魔法为负数时修改成0,财富为负数修改为0即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
typedef long long int ll;
struct node{
ll a,b,c,d;
node(){}
node(ll a,ll b,ll c,ll d):a(a),b(b),c(c),d(d){}
}a[maxn];
ll ans = 0;
int n;
void dfs(int dep,ll hp,ll s){
if(dep >= n){
ans = max(ans,s * hp);
return ;
}
dfs(dep + 1,hp - a[dep + 1].b < 0 ? 0 :hp - a[dep + 1].b,s + a[dep + 1].a);
dfs(dep + 1,hp + a[dep + 1].c,s - a[dep + 1].d < 0 ? 0 :s - a[dep + 1].d);
}
void solved(){
cin>>n;
for(int i = 1; i <= n; i++){
ll x,y,z,q;cin>>x>>y>>z>>q;
a[i] = {x,y,z,q};
}
dfs(1,a[1].c,0);
dfs(1,0,a[1].a);
cout<<ans<<endl;
}
int main(){
solved();
return 0;
}E:Board
题面:
思路:模拟即可。 把每行的值 - 这行最小值(对于任意ai > 0),把每列的值 - 这列最小值(对于任意aj > 0),再用一个变量统计减去了多少就是那么未知数的值。减完之后最后矩阵应该是全0.
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 10;
typedef long long int ll;
int a[maxn][maxn];
void solved(){
int n;cin>>n;
int ans = 0;
for(int i = 1; i <= n; i++){
int mm = 1e6 + 10;
bool flag = true;
for(int j = 1; j <= n; j++){
cin>>a[i][j];
if(a[i][j] != -1)
mm = min(a[i][j],mm);
if(a[i][j] == 0)flag = false;
}
if(!flag)continue;
for(int j = 1; j <= n; j++){
if(a[i][j] != -1)
a[i][j] -= mm;
else ans += mm;
}
}
for(int i = 1; i <= n; i++){
int mm = 1e6 + 10;
bool flag = true;
for(int j = 1; j <= n; j++){
if(a[j][i] != -1)
mm = min(mm,a[j][i]);
if(a[j][i] == 0)flag = false;
}
if(!flag)continue;
for(int j = 1; j <= n; j++){
if(a[j][i] != -1)
a[j][i] -= mm;
else ans += mm;
}
}
// cout<<endl;
// for(int i = 1; i <= n; i++){
// for(int j = 1; j <= n; j++){
// cout<<a[i][j]<<" ";
// }
// cout<<endl;
// }
cout<<ans<<endl;
}
int main(){
solved();
return 0;
}A:小A买彩票
题面:
思路:
一开始看到n非常小直接写了暴力t了,不妨看一下暴力的写法。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
typedef long long int ll;
ll ans;
int n;
void dfs(int dep,int s){
if(dep >= n){
if(s >= 3 * n)ans++;
return ;
}
for(int i = 1; i <= 4; i++){
dfs(dep + 1,s + i);
}
}
void solved(){
cin>>n;
dfs(1,1);
dfs(1,2);
dfs(1,3);
dfs(1,4);
if(n == 0){
cout<<"1/1"<<endl;
}else{
ll res = pow(4,n);
ll _gcd = __gcd(res,ans);
cout<<ans / _gcd <<"/"<<res / _gcd<<endl;
}
}
int main(){
solved();
return 0;
}这个暴力很多部分有重复计算,导致效率过低,所以我们考虑用数组记忆化搜索。注意到对于任意的n,只有[3n,4n]这段满足题面要求,所以我们就枚举这段的数量,用dp数组来记忆之前的结果。就可以避免大量重复计算。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
ll dp[50][550];
//dp[i][j]:第i次抽奖金额为j的数量
ll n;
ll dfs(ll dep,ll s){
//cout<<dep <<" "<<s<<endl;
if(dep > n){
if(s == 0)return 1;
return 0;
}
ll ans = 0;
if(dp[dep][s] != -1)return dp[dep][s];
for(int i = 1; i <= 4; i++){
ans += dfs(dep + 1,s - i);
}
//cout<<ans<<endl;
dp[dep][s] = ans;
return ans;
}
void solved(){
cin>>n;
memset(dp,-1,sizeof(dp));
if(n == 0){
cout<<"1/1"<<endl;
}else{
ll ans = 0;
for(ll i = n * 3; i <= n * 4; i++){
ans += dfs(1,(ll)i);
}
ll res = pow(4,n);
ll _gcd = __gcd(res,ans);
cout<<ans / _gcd <<"/"<<res / _gcd<<endl;
}
}
int main(){
solved();
return 0;
}
京公网安备 11010502036488号