題目鏈接:https://codeforces.com/gym/102028/problem/B
題目描述:
奧特曼打怪獸,有怪獸和 分別對應的生命值爲和攻擊力,按回合制進行攻擊,如果怪物活着,將對奧特曼先造成對應的傷害,在第回合奧特曼打怪的傷害爲,問奧特曼殺死這兩隻怪獸後受到的最小傷害,並對應輸出字典序最小的方案
題解思路:
在貪心上的最優方案一定是優先殺一個人,再殺另一個。
設表示對一個怪獸造成點傷害的最小步數,就是等差數列求個和。
那麼我們一定可以在的時間將兩者全部殺掉。
假設先殺我們總可以保證在的時間殺死並且不浪費一點攻擊力,即在的時間穿插着打,並且殺死
接下來分兩種策略,分別是先殺a和先殺b。
先用三次二分搜索找出分別對應殺光,殺,殺對應的最小步數。
如果先殺的話,就是在穿插打,並打死在全部打
現在的問題就是如何分配打,保證這個字符串字典序最小。
現在有一個和表示還需要多少打(可能不需要),和打的部分可以給多少出去。
我們就倒序在找,如果需要,並且有剩餘,就替換爲
第二種情況是先殺的策略,這種策略在分配打法的時候思維上比較複雜= =
在貪心策略上,依舊考慮和。
順序循環填的情況會出現當前如果填了之後後面無法再填A(不夠了),這個時候就需要移動一下填的位置到需要的地方。這種情況在第一個策略裏面就不需要考慮,因爲倒序循環不會出現這種情況。
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
#define int ll
#define debug cout<<"fuck"<<endl;
const int mod=(int)1e9+7;
const int maxn=(int)3e5+5;
int a[maxn];
int len,len1,len2;
int n,t;
int h1,h2,a1,a2,hur1,hur2;
bool check(int x,int ned)
{
ll sum=(x+1)*x/2;
if(sum<ned)return 0;
else return 1;
}
int sum(int l,int r)
{
return (r-l+1)*(l+r)/2;
}
int cmp(string a,string b)
{
for(int i=1;i<min(a.size(),b.size());i++)
{
if(a[i]==b[i])continue;
else return a[i]>b[i]?1:2;
}
return a.size()>=b.size()?1:2;
}
int binary_search(int x)
{
int l=1,r=(int)1e9,mid;
while(l<r)
{
mid=(l+r)/2;
if(check(mid,x))r=mid;
else
{
l=mid+1;
}
}
return l;
}
string kill_a()
{
string s="";
s+='0';
int ned=h2;
int lef=sum(1,len1)-h1;
for(int i=1;i<=len;i++)
{
if(i<=len1)s+='A';
else
{
s+='B';
ned-=i;
}
}
for(int i=len1;i>=1&&ned>0;i--)
{
if(lef>=i)//如果需要,並且有剩餘
{
lef-=i;
ned-=i;
s[i]='B';
}
}
return s;
}
string kill_b()
{
string s="";
s+='0';
int lef=0;
int ned=h1-sum(len2+1,len);
for(int i=1;i<=len;i++)
{
if(i<=len2)
{
s+='B';
lef+=i;
}
else s+='A';
}
lef-=h2;
for(int i=1;i<=len2&&lef>0;i++)
{
if(lef>=i)
{
if(lef-i<i+1&&ned-i>0)//如果這個位置修改爲A之後,之後不能再修改了,但是還有需要
{
s[ned]='A';
//cout<<"i:"<<i<<' '<<"ned:"<<ned<<endl;
break;
}
lef-=i;
ned-=i;
s[i]='A';
}
}
return s;
}
void sout(string s)
{
for(int i=1;i<s.size();i++)
{
cout<<s[i];
}
cout<<endl;
}
signed main()
{
IOS
cin>>t;
while(t--)
{
cin>>h1>>h2>>a1>>a2;
len=binary_search(h1+h2);
len1=binary_search(h1);
len2=binary_search(h2);
hur1=len1*(a1+a2)+(len-len1)*a2;
hur2=len2*(a1+a2)+(len-len2)*a1;
string fir_kil_a=kill_a();
string fir_kil_b=kill_b();
//cout<<hur1<<' '<<fir_kil_a<<endl;
//cout<<hur2<<' '<<fir_kil_b<<endl;
if(hur1<hur2)
{
cout<<hur1<<' ';
sout(fir_kil_a);
}
else if(hur1>hur2)
{
cout<<hur2<<' ';
sout(fir_kil_b);
}
else
{
if(cmp(fir_kil_a,fir_kil_b)==1)//a大
{
cout<<hur2<<' ';
sout(fir_kil_b);
}
else
{
cout<<hur1<<' ';
sout(fir_kil_a);
}
}
}
return 0;
}