日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

8.23打架学习一个

發布時間:2023/12/10 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 8.23打架学习一个 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

先看題目:
T1:數正方形,數學簽到題,找規律;
T2:取數,看起來很眼熟的一道題,并且何某8.22時告誡我們要考動規。所以顯然。。。不是動規。動規動規念著念著就成“堆”了。
T3:葡萄酒交易,唯一的一道動規+最小生成樹+狀態亞索。

T1:
在n * n的點陣中任取4個點,回答:
問題1:這4個點恰好是“正放”的正方形的4個頂點的方案數是多少?
問題2:這4個點恰好是正方形(包括“正放”和“斜放”)的4個頂點的方案數是多少?

下圖為一個4*4的點陣,上圖表示一種“正放”的方案,下圖表示一種“斜放”的方案。

int main() {//freopen("count.in","r",stdin);//freopen("count.out","w",stdout);re(n);re(k);for(i=1;i<=n-1;i++)ans1+=(n-i)*(n-i);for(i=1;i<=n-2;i++)ans2+=i*i*((n-1)-i);if(k==1)printf("%I64d",ans1%mod);else printf("%I64d",(ans1+ans2)%mod); }

隨便找找規律就可以了。

T2:n個整數組成的一個環,現在要從中取出m個數,取走一個數字就不能取跟它相鄰的數字(相鄰的數不能同時取)。要求取出的數字的總和盡可能大,問這個最大和是多少? 如果無解,請輸出“Error!”
輸入 : 第一行包含兩個正整數n、m。 第二行為n個整數Ai。
輸出:僅一個整數,表示所求結果。如果無解輸出“Error!”,不包含引號。
樣例數據:
in:7 3 1 2 3 4 5 6 7
out:15
in:7 4 1 2 3 4 5 6 7
out:Error!
in:8 4 8 5 6 2 3 4 8 9
out:25

炸一看是動規,不過一看動規是O(2n方),怎么就變成堆了呢?
利用結構體,分別記錄每個數的編號,值,左邊值,右邊值,然后放進一個大根堆里面。每次取出堆頂的數,標記左右不可選的數,用ans把它加起來。注意還沒完,現在要生成一個新的數,值為(左+右-當前數值),并且更新左數和右數,如此,若當前選擇并非最優,就可以重新選擇。
這。只能膜拜想出這個方法的神犇為敬了。

#include<iostream> #include<cstdlib> #include<cstdio> #include<queue> #include<cmath> using namespace std; priority_queue<pair<int,int> >q; const int MAX=-999999999; const int maxn=400200; inline void re(int &d) {char t=getchar();bool f=false;while(t<'0'||t>'9'){if(t=='-')f=true;t=getchar();}for(d=0;t>='0'&&t<='9';t=getchar())d=d*10+t-'0';if(f==true)d=-d; } int n,m,a,b,c,d,e,ans=0,tot=0; int p[maxn],l[maxn],r[maxn]; bool used[maxn]; int main() {re(n);re(m);for(a=1;a<=n;a++){re(p[a]); //錄入值 l[a]=a-1;r[a]=a+1; //記錄左邊和右邊的編號 q.push(make_pair(p[a],a));tot++;}l[1]=n;r[n]=1;if(m>(n/2)){printf("Error!");return 0;}while(m!=0){a=q.top().second;q.pop();if(used[a]==true)continue;ans+=p[a];tot++;p[tot]=p[l[a]]+p[r[a]]-p[a]; //建立新數,用于重新選擇 used[a]=true;used[l[a]]=true;used[r[a]]=true;//標記為已使用; l[tot]=l[l[a]];r[tot]=r[r[a]];l[r[r[a]]]=tot;r[l[l[a]]]=tot; //更新一些亂七八糟的 q.push(make_pair(p[tot],tot)); //新數入堆 m--;}printf("%d",ans);return 0; }

T3:
啊不想寫了,狀態亞索記錄某點是否在集合之中,然后用最小生成樹亂搞一下就可以了。

#include<iostream> #include<cstdlib> #include<cstdio> #include<queue> #include<algorithm> #include<cmath> using namespace std; const int inf=1e9; const int maxn=(1<<17); struct node{int x,y,v; }wine[200]; int i,j,n,m,toot,a[20],father[20],sum[maxn],cost[maxn],f[maxn]; bool cmp(node x,node y){return x.v<y.v;} inline void re(int &d) {bool f=false;char t=getchar();while(t<'0'||t>'9'){if(t=='-')f=true;t=getchar();}for(d=0;t>='0'&&t<='9';t=getchar())d=(d<<3)+(d<<1)+t-'0';if(f==true)d=-d; } int getfather(int x) {if(x!=father[x])father[x]=getfather(father[x]);return father[x]; } int kru(int s) {int i,tot=0,mincost=0,cnt=0;for(i=0;i<n;i++){father[i]=i;if((s>>i)&1)tot++;} for(i=1;i<=m;i++){if(((s>>wine[i].x)&1)&&((s>>wine[i].y)&1)){int fx=getfather(wine[i].x);int fy=getfather(wine[i].y);if(fx!=fy){father[fx]=fy;cnt++;mincost+=wine[i].v;}} }if(cnt+1!=tot)return inf;else return mincost; } int main() {re(n);re(m);for(i=0;i<n;i++)re(a[i]);for(i=1;i<=m;i++){re(wine[i].x);re(wine[i].y);re(wine[i].v);}sort(wine+1,wine+1+m,cmp);toot=(1<<n)-1;for(i=0;i<=toot;i++)for(j=0;j<n;j++){if((i>>j)&1)sum[i]+=a[j];}for(i=0;i<=toot;i++){if(sum[i]==0)cost[i]=kru(i);else cost[i]=inf;}for(i=1;i<=toot;i++)f[i]=inf;f[0]=0;for(i=0;i<=toot;i++){if(sum[i]!=0)continue;for(j=1;j<=toot;j++){if(sum[j]!=0)continue;f[i|j]=min(f[i|j],f[i]+cost[j]);}}if(f[toot]==inf)printf("Impossible\n");else printf("%d\n",f[toot]);return 0; }

就這樣吧。

總結

以上是生活随笔為你收集整理的8.23打架学习一个的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。