WEEK4 CSPシミュレーションのプログラミング

WEEK4 CSPシミュレーションのプログラミング

質問A:クードンの冒険

ググドンは遊び心のある子供で、ある日、彼は古代の遺跡から魔法の指輪を手に入れました。このリングは端から端までのアルファベットで構成され、リングには最初に文字aを指すポインターがあります。ググドンは一度に1フレームずつ時計回りまたは反時計回りに回転できます。たとえば、aは時計回りにzに、反時計回りにbに回転します。グ・グドンは手にひもを持っていますが、彼は愚かすぎるので、彼はあなたに助けを求めに来て、少なくとも何回回さなければならないか尋ねました。
ここに画像の説明を挿入

1.サンプルの入力と出力

入力

hzet

出力

31

2.問題解決のアイデアとコード

各文字と前の文字の時計回りの間隔と反時計回りの間隔のどちらか回転数を計算します。合計は回転の総数です。
コードは次のとおりです。

#include<iostream>
#include<string>
using namespace std;
int main()
{
    int time=0;
    string str;
    cin>>str;
    int size=str.size();
    for(int i=0;i<size;i++)
    {
        int a,b;
        if(i==0)
        {
            a=1;
            b=str[0]-96;
        } else{
            a=str[i]-96;
            b=str[i-1]-96;
        }
        int tmp=a-b;
        if(tmp<0)
            tmp=tmp+26;
        int tmp1=b-a;
        if(tmp1<0)
            tmp1=tmp1+26;
        if(tmp<=tmp1)
            time = time + tmp;
        else
            time = time + tmp1;
    }
    cout<<time<<endl;
    return 0;
}

B:ググドンが食べたい

ググドン試験週が始まり、月曜日はn日間です。彼は試験週の間それほど疲れていたくなかったので、彼は毎日よく食べることを計画しました。彼は毎日揚げ物を食べることに決めました、そしてググドンは毎日揚げ物を購入する必要があります。しかし、消費を刺激するために、shengjianを購入する方法は2つしかありません。①特定の日に一度に2つのshengjianを購入します。②本日から揚げ物を購入し、明日から揚げ物を購入すると、店舗がバウチャーを差し上げ、翌日にバウチャーを使ってもらう。他の購入方法はありません。これら2つの購入方法は無数に使用できますが、Gu Gudongは質素な良質の男の子で、トレーニング後に去り、トレーニングの最後にバウチャーを持つことは許可されていません。Gu Gu Dongはとても金持ちで、Gu Gu Dongが金持ちであることを心配する必要はありませんが、Gu Gu Dongは愚かすぎます。彼は、試験週の間毎日ai shengjianを購入できるかどうかを尋ねたいと思っています。その中で(1≤n≤100000)、(1≤ai≤10000)

1.サンプルの入力と出力

入力

4
1 2 1 2 

出力

2

2.問題解決のアイデアとコード

購入方法は2つしかないので、一度に2つ買うか、今日と明日それぞれに1つ買うか。
したがって、毎日の購入状況を前から後ろにたどり、次のように処理できます。当日の購入状況が奇数の場合、翌日の購入数量は1つ減ります。トラバースされたデータが負の数を示すか、または最終日の購入数がまだ奇数である場合、購入計画は実行できません。それ以外の場合は実行可能です。

コードは次のとおりです。

#include<iostream>
using namespace std;
int main()
{
    int n;
    cin>>n;
    int * p;
    p=new int[n];
    for(int i=0;i<n;i++) {
        cin >> p[i];
    }
    for(int i=0;i<n-1;i++)
    {
        if(p[i]<0)
        {
           cout<<"NO"<<endl;
           return 0;
        }
        if(p[i]%2==1)
            p[i+1]--;
    }
    if(p[n-1]%2==1)
    {
        cout<<"NO"<<endl;
        return 0;
    }
    cout<<"YES"<<endl;
    return 0;
}

質問Cひどい宇宙線

誰もが知っているように、レイセオンはCSの学部生の上限に達しましたが、彼らには天国があり、外に人がいることを知りません。広大な宇宙には、人間の大学院の知識のレベルに到達するために生まれ、国の最初のレベルでさえ、CSPで自然に優れているGou Gouと呼ばれる生き物があります!しかし、最も恐ろしいことは、それができることです宇宙線を送信してください!宇宙線は人々のIQを破壊し、知性低下ストライキを実行する可能性があります!
宇宙線は無限の2次元平面(2次元グリッドマップとして見ることができます)に広がり、初期方向はデフォルトで上向きです。宇宙線は、特定の距離が放出された後、
2つの宇宙線を方向の左右に45∘45 of 方向に分割し、パワーは同時に変化しません。ユニット長。
今、Ruishenは弟をGou Goに挑戦させる必要がありますが、Ruishenは彼のIQを通常の学部のzjmのレベルまで下げたくありません。戦うために知性を減らしなさい」。

ここに画像の説明を挿入

1.サンプルの入力と出力

入力

最初の線nは分割の数、
2番目の線nは各分割が移動した距離です

4
4 2 3 2

出力

ヒットポイント数を出力
39
概略図

2.問題解決のアイデアとコード

ゲーム中に最初に頭に浮かぶのは、直接DFSです。次に、2次元配列を使用して到達したポイントを格納します。しかし、TLEは4ポイントしか通過しませんでした。
コード:

#include<iostream>
#include<algorithm>
using namespace std;
class point
{
public:
    point(){}
    point(int a,int b)
    {
        _a=a;
        _b=b;
    }
public:
    int _a;
    int _b;
};
int dx[]={0,1,1,1,0,-1,-1,-1};
int dy[]={1,1,0,-1,-1,-1,0,1};
int n;
int *p;
int map[600][600]={0};
int pathlength=0;

void addlength(point start,int direaction,int length,int i)
{
    if(i==n)
        return ;
    point newpoint(start._a,start._b);
    for(int j=0;j<length;j++)
    {
        newpoint._a=newpoint._a+dx[direaction];
        newpoint._b=newpoint._b+dy[direaction];
        if(map[newpoint._a+300][newpoint._b+300]!=0)
            continue;
        else {
            pathlength++;
            map[newpoint._a+300][newpoint._b+300]=1;
        }
    }
    int direaction1=(direaction+1)%8;
    int direaction2=(direaction+7)%8;
    addlength(newpoint,direaction1,p[i+1],i+1);
    addlength(newpoint,direaction2,p[i+1],i+1);
}

int main()
{
    cin>>n;
    p=new int[n];
    for(int i=0;i<n;i++)
    {
        cin>>p[i];
    }
    addlength({0,0},0,p[0],0);
    cout<<pathlength<<endl;
}

現在、この問題には2つの実行可能な解決策があります。1つはメモリ検索で、もう1つは対称性を使用して分割プロセスを減らすことです。対照的に、メモリのない検索コードについて考えることをお勧めします。
グラフの範囲は小さい(300 300)ため、各グリッドには8つの方向があります。同じレイヤーで検索する場合は、拡張の方向と開始点を記録します。同じ検索方向と同じ位置にあるポイントがある場合は、この検索をスキップできます。レコード配列は150 300 300 8です。
標準の回答コードを貼り付けます。

#include<iostream>
using namespace std;
int vis[330][330][31][8];
int mp[330][330];
int a[35];
int n,ans;
int dir[8][2]={{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};

void dfs(int x,int y,int cnt,int d)
{
    if(vis[x][y][cnt][d]) return ;
    vis[x][y][cnt][d]=1;
    for(int i=1;i<=a[cnt];i++) {
        x += dir[d][0], y += dir[d][1];
        if (!mp[x][y]) ans++, mp[x][y] = 1;
    }
        if(cnt<n)
        {
            dfs(x,y,cnt+1,(d+1)%8);
            dfs(x,y,cnt+1,(d+7)%8);
        }
}

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    dfs(160,160,1,2);
    cout<<ans<<endl;
    return 0;
}
オリジナルの記事を8件公開 Likes2 訪問数252

おすすめ

転載: blog.csdn.net/lawrenceY/article/details/104981434