A. Bad Triangle
題目:https://codeforces.com/contest/1398/problem/A
題解:一道計算幾何題,只要觀察陣列的第1,2,n個,判斷他們能否構成三角形即可。
必須注意:從反方向判斷時要注意:兩邊之和大於第三邊的反向是:a[1]+a[2]<=a[n]一定注意為小於等於,兩邊之差小於第三邊的反義是:a[n]-a[2]>=a[1]切記注意是大於等於
程式碼:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=50010;
ll t,n;
ll a[N];
int main()
{
ll i,j,k;
cin>>t;
while(t--)
{
bool flag=true;
cin>>n;
for(i=1;i<=n;i++)
cin>>a[i];
if(a[1]+a[2]<=a[n]||a[n]-a[2]>=a[1])
cout<<"1 2 "<<n<<endl;
else
cout<<"-1"<<endl;
}
return 0;
}
B. Substring Removal Game
題目:https://codeforces.com/contest/1398/problem/B
題解:一到關於字串的貪心問題,由於我們要1的個數最大,所以只要找相鄰的1的個數就好,存到陣列後進行排序,由於我們是先手,因此每隔一個取一次。
程式碼:
#include<bits/stdc++.h>
using namespace std;
int a[110];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int i,t;
string s;
cin>>t;
while(t--)
{
cin>>s;
int len=s.length();
int k=0;
int j=0;
for(i=0;i<len;i++)
{
if(s[i]=='1')
k++;
else
{
if(k!=0)
{
a[j++]=k;
k=0;
}
}
}
if(k!=0)
a[j++]=k;
int ans=0;
sort(a,a+j,cmp);
for(i=0;i<j;i++)
{
if(i%2==0)
ans+=a[i];
}
cout<<ans<<endl;
}
return 0;
}
C. Good Subarrays
題目:https://codeforces.com/contest/1398/problem/C
題解:我認為這道題是最難想的,一開始用暴力,TLE在第三組資料。因而不能用這種方法。
線上處理的方法。
我們想想,用子陣列總和減去元素個數,如果是為0,那麼就是好子陣列,如果好子陣列中又包含好子陣列呢?那麼該好子陣列是不是可以分為三個好子陣列。
如果不為0呢?那麼我們是不是可以記錄這個狀態,我們繼續往後探索的的時候突然發現子陣列總和減去元素個數又為我們上次記錄過的狀態。那麼這個子陣列是不是可以拆成我們上次記錄過的狀態子陣列和另一個子陣列減元素個數為0的好子陣列?(仔細思考這裡,非常重要!)
那麼我們層層深入,如果一個子陣列能這樣分為我們已經訪問過的狀態子陣列和一個好子陣列,那麼不就實現線上處理了嗎?因為現在我們只要遍歷一遍陣列了,其他的子陣列我們就可以利用當前已經記錄的子陣列分解獲得。那麼時間複雜度就大大減小了。
那麼我們怎麼記錄之前狀態呢?這裡就要使用map容器了,我們標記所有計算的差值狀態,利用ans統計值即可。若之前標記過兩次,說明我們可以拆成兩種情況:一個差值為標記過的子陣列和一個好子陣列
程式碼:
#include<bits/stdc++.h> //POJ不支援
#define rep(i,a,n) for (int i=a;i<=n;i++)//i為迴圈變數,a為初始值,n為界限值,遞增
#define per(i,a,n) for (int i=a;i>=n;i--)//i為迴圈變數, a為初始值,n為界限值,遞減。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair
using namespace std;
const int inf = 0x3f3f3f3f;//無窮大
const int maxn = 1e5;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
//*******************************分割線,以上為自定義程式碼模板***************************************//
int main()
{
IOS;
int t,n,i,j;
string str;
cin>>t;
while(t--)
{
cin>>n;
cin>>str;
ll ans=0,num=0;
map<int,ll>mp;
mp[0]=1;//當差值為0時就是一個好陣列
rep(i,0,n-1)
{
num+=str[i]-'0';//計算字首和陣列
ans+=mp[num-(i+1)];//加上當前的狀態對應的值
mp[num-(i+1)]++;//記錄上標記一次
//其實好與壞的區別就在於第一個是好還是壞
}
cout<<ans<<endl;
}
return 0;
}
D. Colored Rectangles
題目:https://codeforces.com/contest/1398/problem/D
題解:DP題,我們來思考一下他們的狀態轉移,設我們可以構造的最大矩形數為nnn,(注意:最大矩形數是一定固定的)那麼該狀態的最優解是不是可以轉換為矩形數為n−1n-1n−1的最優解+當前可構建矩形面積的最大值。我們用dp[i][j][k]表示用去了i個R顏色彩棒,j個G個顏色彩棒,k個C顏色彩棒,那麼我們表示矩形數為n−1自然對應的彩棒數要減2了,這裡注意有三種情況都要判斷
需要注意的是必須對其進行排序,因為我們相當於是不斷加入三根彩棒,比較當時擁有的彩棒合成矩形最大值,這就是一個矩形的最優解,再往後推,逐漸得到總矩形的最優解
程式碼:
#include<bits/stdc++.h> //POJ不支援
#define rep(i,a,n) for (int i=a;i<=n;i++)//i為迴圈變數,a為初始值,n為界限值,遞增
#define per(i,a,n) for (int i=a;i>=n;i--)//i為迴圈變數, a為初始值,n為界限值,遞減。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair
using namespace std;
const int inf = 0x3f3f3f3f;//無窮大
const int maxn = 210;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
ll dp[maxn][maxn][maxn];
int r[maxn],g[maxn],b[maxn];
int main()
{
IOS;
int R,G,B,i,j,k;
cin>>R>>G>>B;
rep(i,0,R-1)
cin>>r[i];
rep(i,0,G-1)
cin>>g[i];
rep(i,0,B-1)
cin>>b[i];
//排序
sort(r,r+R);
sort(g,g+G);
sort(b,b+B);
rep(i,0,R)
{
rep(j,0,G)
{
rep(k,0,B)
{
if(i&&j)
dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k]+r[i-1]*g[j-1]);
if(i&&k)
dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k-1]+r[i-1]*b[k-1]);
if(j&&k)
dp[i][j][k]=max(dp[i][j][k],dp[i][j-1][k-1]+g[j-1]*b[k-1]);
}
}
}
cout<<dp[R][G][B]<<endl;
return 0;
}