質問DDL恐怖
問題の説明
ZJMにはn個の課題があり、各課題には独自のDDLがあります。ZJMがDDLの前にこの課題を完了しない場合、教師はこの課題のすべての通常の課題を差し引きます。
したがって、ZJMは、控除をできるだけ少なくするために、宿題の順序を調整する方法を知りたいと考えています。
彼を助けてください!
input:
入力にはT個のテストケースが含まれます。入力の最初の行は、テストケースの数である単一の整数Tです。
各テストケースは、ジョブの数を示す正の整数N(1 <= N <= 1000)で始まります。
次に2行。最初の行にはDDLを示すN整数が含まれ、次の行には控除ポイントを示すN整数が含まれます。
出力:
テストケースごとに、テストケースごとに1行で、最小の合計削減スコアを出力する必要があります。
アイデア
今回は、構造を使用して、各ジョブのスコアとddlを保存します。毎回最高スコアの1つのジョブを取得して、ddlの前の日付が占有されているかどうかを確認します。占有されていない場合はそれを使用し、そうでない場合は破棄します。ここでvisを使用します配列は、日付が占有されているかどうかを示します。複数のデータセットがあるため、毎回0にリセットする必要があります。
コード
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct mm
{
int t,v;
bool operator<(const mm&p)
{
return v>p.v;
}
};
bool vis[1001];
mm shu[1002];
int n,T;
int main()
{
scanf("%d",&T);
while(T--)
{
memset(vis,0,sizeof(vis));
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&shu[i].t);
}
for(int i=0;i<n;i++)
{
scanf("%d",&shu[i].v);
}
sort(shu,shu+n);
int num=0 ;
for(int i=0;i<n;i++)
{
bool flag=1;
for(int j=shu[i].t;j>0;j--)
{
if(vis[j]==0)
{
vis[j]=1;
flag=0;
break;
}
}
if(flag)
num+=shu[i].v;
}
printf("%d\n",num);
}
return 0;
}
まとめ
これは貪欲の典型的な問題でもあり、
質問B 4シリーズ
問題の説明
ZJMには4つのシリーズA、B、C、Dがあり、各シリーズにはn個の番号があります。ZJMは各シーケンスから数値を取得し、4つの数値の合計をゼロにするスキームの数を知りたいと考えています。シーケンスに同じ番号が複数ある場合は、それらを異なる番号として扱います。
彼を助けてください!
入力:
最初の行:n(シーケンスの番号の数を表す)(1≤n≤4000)
次のn行では、i番目の行に4つの番号があり、A、B、C、Dのシーケンスの番号を表しますI番目の数(数は2の28乗を超えない)
出力:
異なる組み合わせの数
アイデア
ここでは、二分法の考え方を使用できます。1つは4つの配列を持ち、2つは前と後を組み合わせて2つの配列を取得できます。0になる可能性がある数は、2つの配列の反対である必要があります。ソートするには、別の配列の各要素の反対の数を使用して、この配列の最初と最後のオカレンスを見つけ、オカレンスの数を取得します。合計数は、可能な組み合わせの数です。
コード
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a1[4001],a2[4001],a3[4001],a4[4001];
int b1[16000111],b2[16000111];
int n;
int find(int t,int num)
{
t*=-1;
int first=-1,last=0;
int l=0,r=num-1;
bool f1=0;
while(l<=r)
{
int mid=(l+r)/2;
if(b1[mid]>=t)
{
if(b1[mid]==t)f1=1;
first=mid;
r=mid-1;
}
else l=mid+1;
}
l=0;
r=num-1;
while(l<=r)
{
int mid=(l+r)/2;
if(b1[mid]==t)
{
last=mid;
l=mid+1;
}
else if(b1[mid]>t)r=mid-1;
else l=mid+1;
}
if(f1) {//printf("%d\n",t);
return last-first+1;}
else return 0;
}
int main()
{
int num=0,count=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d%d%d%d",&a1[i],&a2[i],&a3[i],&a4[i]);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
b1[num]=a1[i]+a2[j];
b2[num++]=a3[i]+a4[j];
}
sort(b1,b1+num);
for(int i=0;i<num;i++)
{
count+=find(b2[i],num);
}
cout<<count<<endl;
return 0;
}
まとめ
悲しいかな、最初にクラスでpptを調べたときに邪悪な反対の番号が書かれていましたが、
間違った答えを得るたびに、配列で反対の番号を見つけるのを忘れていましたo(╥﹏╥)o
C質問DDL恐怖
問題の説明
TTは毎日ステーションBの猫チャンネルに夢中になる真面目な猫好きです。
ある日、TTの友人であるZJMがTTに問題を与えることを決定しました。TTがこの問題を解決できる場合、ZJMはかわいい猫を購入してTTに与えます。
タスクの内容は、N個の配列cat [i]が与えられ、この配列を使用して新しい配列ans [i]を生成します。新しい配列は、任意のi、j、およびi!= Jと同様に定義され、すべてans [] = abs(cat [i] -cat [j])、1 <= i <j <= Nを持ちます。この新しい配列の中央値を見つけてください。中央値は、ソート後の(len + 1)/ 2の位置に対応する数値であり、「/」は切り捨てられます。
TTはとてもかわいい猫を飼いたいのですが、手伝ってもらえますか?
入力:
複数の入力セット。Nを入力するたびにNの数があることを示し、次に長さNのシーケンスを入力しますcat、cat [i] <= 1e9、3 <= n <= 1e5
出力:
新しい配列の中央値数
アイデア
最初に元の配列を並べ替えて、新しい配列の要素値の範囲を計算します。この範囲で、バイナリの回答はPを見つけます(Pは中央値)。各Pについて、新しいシーケンスでのPのランクを計算します。
元の数値シーケンスが並べ替えられているため、絶対値に移動してXj <= Xi + Pを取得し、下付き文字iを列挙して、条件を満たす下付き文字jの数を計算できます。ここでの計算では、バイナリ検索を使用して最初の値以上の最初の値も検索しますXi + Pの数の位置、および条件を満たすすべてのjの合計は、条件を満たす2進タプルの対数です。数値と中央値のランクを比較してください。側では、ランクが中央値より大きい場合、中央値は左側にあり、新しい配列要素の値の範囲はそれに応じて更新されます。2つの数値が等しい場合、Pは中央値です。
コード
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int cat[100001];
int n;
int find(int t )
{
int l=0,r=n-1,ans=-1;
while(l<=r)
{
int mid=(l+r)/2;
if(cat[mid]>=t)
{
ans=mid;
r=mid-1;
}
else l=mid+1;
}
return ans;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;i++)
scanf("%d",&cat[i]);
sort(cat,cat+n);
int l=0,r=cat[n-1]-cat[0],ans=0;
int zh=(n*(n-1)/2+1)/2;
while(l<r)
{
//int mingci=0;
int mid = (l+r)/2;
int mingci = 0;
for(int i=0;i<n;i++)
{
int rr = find(cat[i]+mid);//小于mid的个数
if(rr!=-1)
mingci+= (n-rr);//计算mid名次
}
if(mingci>(n*(n-1)/2-zh))//寻找第一个0出现
{
ans = mid;
l = mid +1;
}
else r = mid;
}
cout<<ans<<endl;
}
return 0;
}
まとめ
最初はPPTで与えられたアイデアについてあまり理解していませんでしたが、その後、具体的な意味を理解する前に長い間考えました。