A(贪心)
题意:共有n种牌,接下来n行,第i行一个整数Ai表示号码为i的牌有Ai张,当两张牌号码的绝对值小于等于1时,就可以凑成一对,问最多可以凑成几对。
思路:当牌数为偶数时,就与号码一样的配对,当牌数为奇数时,就用掉一张下一个号码的牌来配对。
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n;
void solve()
{
cin>>n;
vector <int> a(n+1);
for(int i = 1 ; i <= n ; i++)
{
cin>>a[i];
}
ll ans = 0;
for(int i = 1; i <= n; i++)
{
if(a[i]&1)
{
ans+=a[i]/2;
if(a[i+1]!=0)
{
a[i+1]--;
ans++;
}
}
else
{
ans+=a[i]/2;
}
}
cout<<ans<<'\n';
}
int main()
{
//ios;
int _t=1;
//cin>>_t;
while(_t--)
{
solve();
}
system("pause");
return 0;
}
B(思维)
题意:起初有1克金子,0克银子,在接下来的n天里,每天有一个汇率x,可以A克金子换成xA的银子,也可以将A的银子换成A/x的金子,或者不进行交换。给出接下来n天的汇率,问如何交换可以获得最多的金子
思路:将每天的汇率画成函数图,则一定在高峰换银子,低谷换金子。注意最后一次要换成金子,当交换次数为奇数时,去掉最后一次交换即可
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n;
void solve()
{
cin>>n;
vector<int>a(n+2);
vector<int>ans(n+2);
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
a[n+1]=a[n]+1;
int flag=0;
int cnt=0;
for(int i = 1 ;i <= n;i ++)
{
if(flag == 0 && a[i] >= a[i-1]&&a[i] >= a[i+1])
{
flag = 1;
ans[i] = 1;
cnt++;
}
else if(flag == 1 && a[i] <= a[i-1] && a[i] <= a[i+1])
{
flag=0;
ans[i]=1;
cnt++;
}
}
if(cnt&1)
{
for(int i = n; i >= 1; i--)
{
if(ans[i])
{
ans[i]=0;
break;
}
}
}
for(int i = 1; i<= n; i++)
{
cout<<ans[i]<<" \n"[i==n];
}
}
int main()
{
//ios;
int _t=1;
//cin>>_t;
while(_t--)
{
solve();
}
system("pause");
return 0;
}
M(思维)
题意:给你四种字符串“((" , "()" , ")(" , "))"的个数a,b,c,d。问能否拼出合法序列
思路:第二种不用管。第一种和第四种的个数一定要相等才能使左右括号个数相等。第三种放在序列中间即可,会消耗掉一个左括号一个右括号。
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
int a,b,c,d;
void solve()
{
cin>>a>>b>>c>>d;
if(a == d && a>0)
{
cout<<1<<'\n';
return ;
}
if(a == d && a==0 && c==0)
{
cout<<1<<'\n';
return ;
}
cout<<0<<'\n';
}
int main()
{
//ios;
int _t=1;
//cin>>_t;
while(_t--)
{
solve();
}
system("pause");
return 0;
}
E(思维)
题意:一个A*B*C的长方体由1*1*1的小长方体组成,问如何将大长方体分成两个小长方体,使两个小长方体的体积差最小。
思路:当有一条边为偶数时,从中点对半分,差值最小为0。当三条边都是奇数时,切分后两个小长方体的体积总是差一排小长方体,要使体积差最小,只需从A*B,A*C,B*C中取最小。
所以,答案就是三个边中的一个边%2与另外两个边的乘积,最后取三种情况的最小值,简洁明了。
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
ll a,b,c;
void solve()
{
cin>>a>>b>>c;
ll ans=min((a%2)*b*c,min((b%2)*a*c,(c%2)*a*b));
cout<<ans<<'\n';
}
int main()
{
//ios;
int _t=1;
//cin>>_t;
while(_t--)
{
solve();
}
system("pause");
return 0;
}
K(博弈)
题意:有n个节点的无根树,其中有一个特殊节点x,给出n-1条边。每次操作可以删除一个叶子节点及其边,谁删除特殊节点x谁获胜,Ayush先手,问谁会获胜。
思路:当x为叶子节点时,先手胜。否则,选择x为根重构这棵树,二者都是先删除叶子节点,
直至x的每棵子树只剩一个节点时。
然后二者删除x的儿子节点,直至x的度为1时(只剩一条边时),下一位玩家获胜。
此过程中,共删除了n-2条边,只需讨论n-2或n的奇偶即可。当n为偶数时, Ayush胜;n为奇数时,Ashish胜
注意特判当n等于1时,Ayush胜。
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n,x;
void solve()
{
cin>>n>>x;
if(n == 1)
{
cout<<"Ayush\n";
return ;
}
int cnt=0;
for(int i = 1; i <= n-1 ; i++)
{
int u,v;
cin>>u>>v;
if( u == x || v == x ) cnt++;
}
if(cnt == 1 || n%2 == 0) cout<<"Ayush\n";
else cout<<"Ashish\n";
}
int main()
{
//ios;
int _t=1;
cin>>_t;
while(_t--)
{
solve();
}
system("pause");
return 0;
}
H
题意:有一个h*w的矩阵,在矩阵的每个格上有两个数Ai和Bi,可以选择将一个涂成红色,另一个就被涂成蓝色。现在从(1,1)移动到(h,w),只能向下或向右移动,求最后走到(h,w)时路径上蓝色总值与红色总值差的绝对值最小是多少
思路:bool型dp[i][j][k]表示在位置(i,j)时,路径上蓝红差值k能否取到。则它是由上面位置和左面位置转移过来。由于Ai,Bi∈[0,80],h,w∈[2,80]所以路径上差值最大为(h+w-1)*80.由于差值可为负,为避免数组越界可以将k数组开到12800*2,用k与12800的差值表示路径上差值。
#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
#define endl '\n'
#define sf(x) scanf("%d",&x)
#define rep(i,x) for(i=0;i<(x);i++)
#define gen(x) x##_
#define ios std::ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
bool dp[85][85][12810*2];
int h,w;
int a[85][85],b[85][85],d[85][85];
void solve()
{
cin >> h >> w;
for(int i = 1; i <= h; i++)
for(int j = 1; j <= w; j++)
cin >> a[i][j];
for(int i = 1; i <= h; i++)
for(int j = 1; j <= w; j++)
{
cin >> b[i][j];
d[i][j] = a[i][j] - b[i][j];
}
dp[1][1][12800+d[1][1]] = 1;
dp[1][1][12800-d[1][1]] = 1;
for(int i = 1; i <= h ; i++)
{
for(int j = 1;j <= w; j++)
{
if(i == 1 && j == 1) continue;
for(int k = 0; k <= 12800*2; k++)
{
int tem1=d[i][j];
int tem2=-d[i][j];
dp[i][j][k]=dp[i-1][j][k-tem1]||dp[i-1][j][k-tem2]||dp[i][j-1][k-tem1]||dp[i][j-1][k-tem2];
}
}
}
int ans=inf;
for(int i = 0; i <= 12800*2; i++)
{
if(dp[h][w][i])
{
ans=min(ans,abs(i-12800));
}
}
cout<<ans<<'\n';
}
int main()
{
//ios;
int _t=1;
//cin>>_t;
while(_t--)
{
solve();
}
system("pause");
return 0;
}