1. 程式人生 > 實用技巧 >Consonant Fencity Gym - 101612C 暴力二進位制列舉 Intelligence in Perpendicularia Gym - 101612I 思維

Consonant Fencity Gym - 101612C 暴力二進位制列舉 Intelligence in Perpendicularia Gym - 101612I 思維

題意1:

給你一個由小寫字母構成的字串s,你可以其中某些字元變成大寫字母。如果s中有字母a,你如果想把a變成大寫,那s字串中的每一個a都要變成A

最後你需要要出來所有的字元對,s[i]和s[i-1]需要是子音字母,且s[i]和s[i-1]中需要一個字母大寫另一個小寫。a、e、i、o、u、w、y這七個字母是母音

輸出最大字元對數量

題解1:

首先預處理一下s字串中字元相鄰的數量,就是記錄w[s[i-1]][s[i]]的數量

之後二進位制列舉所有字母變成大寫的情況。

然後列舉這個字母變成大寫之後和其他字母組成成為字元對的數量。也就是結果加上w[x][k](x是變成大寫的字母,k是列舉x和那個字母組成字元對)

那麼如果b和c在s字串中相鄰了,然後b和c都變成大寫怎麼處理?

列舉到b變成大寫的時候,x='b',當k='c'這個時候需要加上w[x][k]。

到下一次列舉到c的時候,x='c',當k='b'我們判斷k是否變成了大寫,如果變了,就減去w[x][k]

AC程式碼:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include 
<map> #include <queue> #include <set> #include <vector> using namespace std; typedef long long ll; const int maxn = 1e6 + 5; const int mod = 1000000007; char s[maxn]; int w[150][150],que[150],vis[150]; int main() { freopen("consonant.in","r",stdin); freopen("consonant.out","w",stdout); scanf(
"%s",s); int len=strlen(s); if(len==1) { printf("%s\n",s); return 0; } for(int i=1;i<len;++i) { w[s[i-1]][s[i]]++; } int pos=0; for(int i='a';i<='z';++i) { if(i=='a' || i=='e' || i=='o' || i=='u' || i=='i' || i=='w' || i=='y') continue; que[pos++]=i; } //printf("%d***\n",pos); int ans=0,flag=0; for(int i=0;i<(1<<pos);++i) { int sum=0; memset(vis,0,sizeof(vis)); for(int j=0;j<pos;++j) { if((1<<j)&i) { for(int k='a';k<='z';++k) { if(k=='a' || k=='e' || k=='o' || k=='u' || k=='i' || k=='w' || k=='y' || k==que[j]) continue; if(vis[k]) { // if(i==1026) // { // printf("********%c %c %d %d\n",k,que[j],w[k][que[j]],w[que[j]][k]); // } sum-=w[k][que[j]]; sum-=w[que[j]][k]; } else { // if(i==1026) // { // printf("%c %c %d %d\n",k,que[j],w[k][que[j]],w[que[j]][k]); // } sum+=w[k][que[j]]; sum+=w[que[j]][k]; } } vis[que[j]]=1; } } if(ans<sum) { ans=sum; flag=i; } // printf("%d***\n",sum); // system("pause"); } memset(vis,0,sizeof(vis)); for(int i=0;i<pos;++i) { if((1<<i)&flag) { vis[que[i]]=1; } } for(int i=0;i<len;++i) { if(vis[s[i]]) printf("%c",s[i]-32); else printf("%c",s[i]); } printf("\n"); return 0; }

題意2:

按順序給你n個點,表示第i個點和第i-1個點相連,第1個點和第n個點相連。

題目保證所有連線和x或者y軸平行。讓你輸出n個點構成的圖形看不到區域的長度

題解:

首先設這n個點構成的圖形周長為x,後面使用x-大矩形周長就是答案

大矩形周長:就是把圖形補全之後的外層大矩形的周長

程式碼:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 5;
const int INF=0x3f3f3f3f;
const int mod = 1000000007;
struct Node
{
    int x,y;
}node[maxn];
int main()
{
    freopen("intel.in","r",stdin);
    freopen("intel.out","w",stdout);
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d",&node[i].x,&node[i].y);
    }
    int ans=0,minnx=INF,minny=INF,maxxx=0,maxxy=0;
    node[n+1]=node[1];
    for(int i=2;i<=n+1;++i)
    {
        minnx=min(minnx,node[i].x);
        minny=min(minny,node[i].y);
        maxxx=max(maxxx,node[i].x);
        maxxy=max(maxxy,node[i].y);
        if(node[i-1].x==node[i].x)
        {
            ans+=abs(node[i].y-node[i-1].y);
        }
        else if(node[i-1].y==node[i].y)
        {
            ans+=abs(node[i].x-node[i-1].x);
        }
    }
    printf("%d\n",ans-((maxxx-minnx)*2+(maxxy-minny)*2));
    return 0;
}
/*
10
1 1
6 1
6 4
3 4
3 3
5 3
5 2
2 2
2 3
1 3
*/