NOIP2010 普及組 蒟蒻的題解報告
看到標題有人就要問了:你剛寫完2017怎麼跑去寫2010了?
當然是因為 2011-2016的題目我都沒做完唄
事實上每年都是A了3題,卡在第四題,而2010年的題目難度都不太高……
(我太弱了額啊)
下方正文——
T1 數字統計
原題連結
自古T1大水題,自古T4是DP。
(然而T4博弈論)
但是!這並不能阻擋 T1 簡單的事實
T1 的演算法非常簡單,列舉直接上即可,也沒什麼需要注意的點
列舉 L 到 R 之間的每個數,將每個數的每一位拆開來再判斷即可
那麼怎麼拆開呢?這對初學者來說可能是個難題(比如說當初的我)
讓我們思考一下:
一個數,如果個位為0,餘下來的數必然可以被10整除,而個位就是餘數
也就是說,我們將一個數 對 10 取餘(即 模10)
而 整除 10 就可以去掉個位了
於是就很容易實現了
程式碼如下:
#include<iostream>
using namespace std;
int main()
{
int ans,i,l,r,j;
ans=0;
cin >> l >> r;//讀入
for(i=l;i<=r;i++)//開始列舉
{
j=i;//不好直接對i下手
while(j>0)
{
if(j%10==2) ans++;//如果個位是2,ans+1
j=j/10 ;//去掉個位
}
}
cout << ans << endl;//輸出
return 0;
}
T2 接水問題
原題連結
這題我選用的是 貪心大法
(事實上這題也可以列舉每秒,那樣比較煩,也比較慢)
做法:每輸入一個時間,就把它加到 目前被佔用時間最小 的水龍頭那裡
那麼這裡就很簡單了,每次排序即可
有人會擔心時間複雜度,事實上只有
當然這裡要借用一下 STL 的 sort 函式
用法就不多說了
程式碼如下:
#include<cstdio>
#include<algorithm>
using namespace std;
int n,p,m,top[10005];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&p);//每次讀入一個時間
top[1]+=p;//加到佔用時間最小的水龍頭上
sort(top+1,top+m+1);//排序
}
printf("%d",top[m]);//由於最後排序了一次,所以陣列尾一定是最大的數
return 0;
}
T3 導彈攔截
原題連結
(事實上有兩道導彈攔截,而兩道完全不同)
這題也挺水的,用 列舉大法 即可
做法:讀入一對座標,算出它距離A裝置的距離,再從大到小排一遍序
接著我們從頭開始向後列舉分界點,分界點右邊導彈的歸A裝置,左邊的歸B裝置
我們知道如果系統去攔截導彈,那麼可以順帶把距離更短的導彈也解決了
所以我們不用擔心攔截不了什麼的
而我們在這些列舉中取最小值就可以得到答案
程式碼如下:
#include<iostream>
#include<algorithm>
using namespace std;
int n,ans1,ans2,ax,ay,bx,by,ans;
struct node
{
int x,y,n;//xy為座標,n代表距離
}a[100005];
int RT(int a,int b,int aa,int bb)
{
return (a-aa)*(a-aa)+(b-bb)*(b-bb);
//計算距離,由於輸出的是平方和所以不用開根號
}
bool cmp(node x,node y)
{
return x.n > y.n;//按距離從大到小排
}
int Max(int x,int y)
{
return x > y ? x : y;
}
int Min(int x,int y)
{
return x < y ? x : y;//手打速度較快
}
int main()
{
cin >> ax >> ay >> bx >> by >> n;
for(int i=1;i<=n;i++)
{
cin >> a[i].x >> a[i].y;
a[i].n=RT(a[i].x,a[i].y,ax,ay);//計算距離
}
sort(a+1,a+n+1,cmp);//排序
ans1=a[1].n;
ans=a[1].n;//初值記得設定,可能有特例
ans2=-2147400000;
for(int i=2;i<=n+1;i++)
{
ans1=a[i].n;//上方已經說明過的過程,右邊歸A系統
int cnt=RT(a[i-1].x,a[i-1].y,bx,by);
ans2=Max(ans2,cnt);//左邊歸B系統
ans=Min(ans,ans1+ans2);//存值
}
cout << ans << endl;//輸出
return 0;
}
T4 三國遊戲
博弈論傷不起啊!
——Venus
是的……作為一個蒟蒻……博弈論是我心中永遠的痛……
實在太難理解了啊喂!(╯‵□′)╯︵┻━┻
不過我還是做出來了……
這道題目的決策(我都不知道是不是這麼說)是這樣的:
由於AI每次取走的是與我們手上組成的組合默契值最高的,那麼我們每次取第二高的,好的就被我們選走了,AI很被動,而他的最好的已經被我們取走了,所以AI就只能取第二強的了,這樣就相當於 “他強任他強,我選託比昂”
舉個栗子:
編號 | 1 | 2 | 3 | 4 |
---|---|---|---|---|
1 | 無 | 55 | 13 | 46 |
2 | 55 | 無 | 44 | 52 |
3 | 13 | 44 | 無 | 32 |
4 | 46 | 52 | 32 | 無 |
我們先取2,AI取走1,我們趁機取4,AI就只能取3
這樣我們的默契值就是52,AI就只有13
程式碼如下:
#include<iostream>
#include<algorithm>
using namespace std;
int n,a[505][505],ans;
bool cmp(int x,int y)
{
return x > y;
}
int main()
{
cin >> n;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
cin >> a[i][j];//讀入
a[j][i]=a[i][j];//構建圖表
}
}
for(int i=1;i<=n;i++)
{
sort(a[i]+1,a[i]+n+1,cmp);//排序,從大到小排
ans=max(ans,a[i][2]);//每次取第二大的即可
}
cout << "1" << endl << ans << endl;//由於我們必勝,所以輸出1就可以了
return 0;
}
小結
2010年的題目算是較為簡單的,就是第四題對於思考的難度比較大,還是需要動腦子的!
原創 By Venus
寫的不好大佬輕噴