【ACPC2013】馬里奧賽車(01揹包)
這裡終究是個技術社群,老是在這裡寫中二少年的風花雪月也不大好,來寫一篇題解。
這題目混進了軟體工程大一新生的java基礎題目裡,與其他設計類、熟悉語法的題目格格不入不講武德。我一查來源,好傢伙是中東+非洲的大學生程式競賽,老師找到這題目也是不容易,而且各大OJ上也沒有。
題目大意
路上有n個車站,你有m個硬幣,每個硬幣都有自己的能量和使用成本,每組資料有成本限制l。
從a車站跳躍到b車站的方法是:使用一些硬幣的組合,使這些硬幣的能量恰好等於兩車站距離(座標之差之絕對值)。
對於一次跳躍,每硬幣只能用一次且使用的硬幣成本之和不超過l。
你的目的是從座標最小的車站跳躍到座標最大的車站,使跳躍次數儘可能少。
輸入格式
第一行給定資料組數T
接下來T組資料,每組資料:
第一行n(<=100),m(<=100),l(<=1000)
接下來一行中n個數,分別是n個車站的座標(無序)
接下來m行,每行兩個數,代表該硬幣成本與能量
輸出格式
T行,代表每組資料最小跳躍次數,若不能到達輸出-1
這道題目,首先想到最後找次數是最短路,但由於是記錄次數,則此題無邊權(邊權相等),所以我直接廣搜。
接下來主要思考怎樣連邊。
其實題目說得很直白了,看到恰好二字,想到NOIP2018d1t2,判斷將不同面額的貨幣能否湊為某特定值,使用了完全揹包(因為每種貨幣數量不限)。
然而此題又增加了成本限制,所以不能用單純的01揹包解決。顯然,對於待湊路程的最優情況就是成本最低,所以與一般意義上揹包湊出最大價值不同,這道題需要找到最小成本。
那麼題意中硬幣的成本轉化為一般揹包的價值;
題意中硬幣的能量轉化為一般揹包的重量。
既然追求最小,則需要初始化最小可能路程~最大可能路程為無窮大。這樣資料更新只能從容量為0的狀態開始,凡是不能正好湊出的路程數,成本均為無窮大。
狀態f[j]代表跳躍j路程所需最小成本。
則狀態轉移方程f[j]=min(f[j],f[j-ci]+vi)
這樣當僅f[abs(兩座標之差)]<=l時,兩車站連邊。
由於資料較小,直接使用鄰接矩陣。
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int tt=sc.nextInt();
int[] a=new int[105];
int[] vis=new int[105];
int[] f=new int[1005];
int[][] x=new int[105][105];
while(tt-->0){
int n=sc.nextInt();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)x[i][j]=0;
for(int i=1;i<=n;i++)vis[i]=0;
int m=sc.nextInt();
int l=sc.nextInt();
int max=-1<<20,min=1<<20,maxn=0,minn=0;
for(int i=1;i<=n;i++){
int tmp=sc.nextInt();
if(tmp>max){max=tmp;maxn=i;}
if(tmp<min){min=tmp;minn=i;}
a[i]=tmp;
}
for(int i=1;i<=max-min;i++)f[i]=1<<30;
for(int i=1;i<=m;i++){//DP
int w=sc.nextInt();
int v=sc.nextInt();
for(int j=max-min;j>=v;j--)
f[j]=Math.min(f[j],f[j-v]+w);
}
/* for(int i=1;i<=max-min;i++) System.out.print(f[i]+" ");*/
for(int i=1;i<n;i++)//連邊
for(int j=i+1;j<=n;j++)
if(f[Math.abs(a[i]-a[j])]<=l){x[i][j]=1;x[j][i]=1;}
/*for(int i=1;i<=n;i++) {
for (int j = 1; j <= n; j++) System.out.print(x[i][j] + " ");
System.out.println();
}*/
Queue<Integer> q = new LinkedList<Integer>();//java的佇列宣告還找了半天
Queue<Integer> qx = new LinkedList<Integer>();
q.add(minn); qx.add(0); vis[minn]=1;//準備廣搜
int fl=0;
while(!q.isEmpty()){
int e=q.poll(); int ex=qx.poll();
if(e==maxn){
System.out.println(ex);
fl=1;
break;
}
for(int i=1;i<=n;i++)
if(x[e][i]==1&&vis[i]==0){q.add(i);qx.add(ex+1);vis[i]=1;}
}
if(fl==0)System.out.println("-1");
}
}
}
注意揹包DP中,f陣列中每個值都是最優的,不只是f[揹包容量]有用。
相關文章
- Sensor Tower:《馬里奧賽車》首月收入達3740萬美元
- NPD:《馬里奧賽車8》成美國史上銷售最快的賽車遊戲遊戲
- 【模板】01揹包、完全揹包
- 01 揹包
- 揹包問題(01揹包與完全揹包)
- 01揹包、完全揹包、多重揹包詳解
- Sensor Tower:《馬里奧賽車巡迴賽》首月下載量達到1.24億
- 《馬里奧賽車》能從《QQ飛車》和《跑跑卡丁車》中學到什麼?
- 01揹包、有依賴的揹包
- 任天堂怎樣才能讓《馬里奧賽車》手遊叫好又叫座?
- 《馬里奧賽車巡迴賽》將於9月登陸iOS和安卓平臺iOS安卓
- 01揹包問題
- 01 揹包問題
- POJ 2184 (01揹包)
- 使用Gym和CNN構建多智慧體自動駕駛馬里奧賽車CNN智慧體自動駕駛
- 01揹包和完全揹包問題解法模板
- 《馬里奧賽車》手遊化面臨的挑戰:照搬主機版不可取
- 01 揹包的變形
- javascript演算法基礎之01揹包,完全揹包,多重揹包實現JavaScript演算法
- 超級馬里奧:奧德賽:箱庭世界,一景一物皆可玩
- 2. 01揹包問題
- 資訊學奧賽一本通 1272:分組揹包(evd)
- 01揹包面試題系列(一)面試題
- 01揹包問題的解決
- 用各種方法解01揹包
- ZOJ 3956——Course Selection System(01揹包)
- 遊戲論·現實的媒介:《超級馬里奧:奧德賽》中的媒介哲學遊戲
- 你真的懂01揹包問題嗎?01揹包的這幾問你能答出來嗎?
- 《馬里奧賽車》手遊開測:豎屏介面自動加速,簡化了操作,增加了氪金
- GfK:2020年歐洲最暢銷實體遊戲 《FIFA 21》、《動森》、《馬里奧賽車8》上榜遊戲
- 馬里奧的中國“學徒”們
- 從【零錢兌換】問題看01揹包和完全揹包問題
- 動態規劃--01揹包問題動態規劃
- 動態規劃 01揹包問題動態規劃
- 01揹包優先佇列優化佇列優化
- 動態規劃-01揹包問題動態規劃
- 【動態規劃】01揹包問題動態規劃
- 任天堂財報:截止2023年11月《馬里奧賽車8:豪華版》銷量達5701萬份