質問選択質問A
タイトルの説明
[Math Processing Error]に正の数を指定すると、ZJMは[Math Processing Error]と合計される[Math Processing Error]を正確に選択できます。今、ZJMはそれを取得する方法がいくつあるのか疑問に思っています!
入力:
最初の行、整数[演算処理エラー]は、テストケースの数を示します。いずれの場合も、2つの行があります。最初の行の3つの整数は、[演算処理エラー]、[演算処理エラー]、および[演算処理エラー]を示します。2行目の[Math Processing Error]整数は正の数を示します。
出力:
いずれの場合も、整数は答えを独立した行で示します。
アイデア
ここでは、すべての数値が配列に格納されています。この配列は、dfs再帰演算を実行します。再帰がk回の場合、それが正しいかどうかが判断されます。k回の前にSより大きいため、時間を節約するために再帰を事前に終了する必要があります。
コード
#include<iostream>
using namespace std;
int n,K,S,ans;
int a[100];
void dfs(int k,int sum,int end)
{
if(sum>S)return;//提前退出
if(k==K)
{
if(sum==S) ans++;
}
else
{
for(int i=end;i<n;i++)
dfs(k+1,sum+a[i],i+1);
}
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n>>K>>S;
for(int i=0;i<n;i++)
cin>>a[i];
ans=0;
dfs(0,0,0);
cout<<ans<<endl;
}
return 0;
}
まとめ
遊び心があり、グループ内の通知に注意を払っていないため、私はこの割り当てに罪を犯しています。この割り当てが終了するまで、私は問題を見つけませんでしたo(╥﹏╥)o
問題Bの選択
タイトルの説明
数直線にn個の閉じた区間[a_i、b_i]があります。各間隔に少なくとも1つのポイントが存在するようにできるだけ少ないポイントを取ります(異なる間隔に含まれるポイントは同じでも
かまいません)入力:
最初の行に1つの整数N(N <= 100)
行2〜N + 1 、1行あたり2つの整数a、b(a、b <= 100)
出力:
選択されたポイントの数を表す整数
アイデア
この質問の意味は非常に明確です。ここでは、この貪欲な基準を使用して、残りの区間で最小の右ノードを取り、その左ノードを以前に選択した区間の右ノードである参照点と比較します。どのように右ノードよりも小さくできますか? 1つのポイントを共有できます。それ以外の場合、参照ポイントは新しい間隔の右側のノードに更新されます。ここでは、すべての間隔が右ノードで非減少的にソートされ、要素はそれらから順次取得されます。
コード
#include<iostream>
#include<algorithm>
using namespace std;
struct mm
{
int l,r;
mm(){};
mm(int a,int b):l(a),r(b){};
bool operator<(const mm&p)
{
return r<p.r;
}
};
mm shu[101];
int n;
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>shu[i].l>>shu[i].r;
}
sort(shu,shu+n);
int count=0,nowp=-1;
for(int i=0;i<n;i++)
if(shu[i].l>nowp)
{
nowp=shu[i].r;
count++;
}
cout<<count<<endl;
return 0;
}
まとめ
この質問を通じて、Konjacは、cmp関数の小なり記号と小なり記号をオーバーロードするトリックを理解できます。次のcmp関数に示すように、aとbは、配列の最初の2つの項目a <bこれは、ソート後の配列内の関係を意味します。この場合、それはインクリメンタル関係です。オーバーロードが符号よりも小さい場合、呼び出された構造体またはクラスは前の要素と見なすことができます。関数の内部表現はcmp関数と同じです。これもインクリメンタル関係です。鶏の理解
bool operator<(const mm&p)
{
return r<p.r;
}
bool cmp(const int &a,const int &b)
{
return a<b;
}
C質問間隔カバレッジ
タイトルの説明
数直線にn(1 <= n <= 25000)の閉区間[ai、bi]があります。指定された線分[1、t](1 <= t <= 1,000,000)をカバーするために、できるだけ少ない区間を選択してください。
ポイント全体をカバーします。つまり、(1,2)+(3,4)は(1,4)をカバーできます。
入力:
最初の行:NとTは、指定された区間番号と対象となる区間の右端の値を示します
。2番目の行からN + 1の行:各行は閉じた区間です。
出力:
選択した間隔の数。-1を出力することはできません
アイデア
今回は、左端点を減少しない順序で使用して配置します。レコードの左端値ごとに、配列から、左端点が現在のレコードの左端値以下で、右端値ができるだけ大きい要素を見つける必要がありますできるだけ少ない間隔で間隔全体をカバーするように更新します。
コード
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
struct mm
{
int l,r;
bool operator<(const mm&p)
{
return l<p.l;
}
};
mm shu[25002];
int n,T,S=1;
int main()
{
scanf("%d%d",&n,&T);
for(int i=0;i<n;i++)
{
scanf("%d%d",&shu[i].l,&shu[i].r);
}
sort(shu,shu+n);
int n_x=1,n_y=0,count=0;
int i=0;
while(n_x<=T&&i<n)
{
if(shu[i].l>n_x) break;
bool flag = 0;
for(;i<n&&shu[i].l<=n_x;i++)
{
if(shu[i].r>n_y)
{
n_y=shu[i].r;//更新最右值
flag=1;
}
}
if(flag)
{
count++;
n_x=n_y+1;
}
}
if(n_x>T) printf("%d\n",count);
else printf("-1\n");
return 0;
}
まとめ
最初は、フラグの必要性は考慮されていません。正しいエンドポイント値の更新ごとにカウント++が実行されたため、結果は良好でした。正しい値が更新されたことを示すフラグが設定され、1回追加するという問題が解決されました。